Fixed #34 Customizing scipy's oaconvolve - #35
Conversation
|
Review these changes at https://app.gitnotebooks.com/stumpy-dev/sliding_dot_product/pull/35 |
The challenger is the customized version of scipy's oaconvolve.
Observations:
For me, the important one is the first bullet point. Of the four optimization opportunities mentioned in this comment, I've addressed 1, 2, and 3 in this PR. The last item, which is about adjusting the number of multiplication for real-valued arrays, can be explored next. |
|
As a gentle reminder, even if we can do things faster, we will never (??) remove the public |
|
Good reminder. It makes sense!! |
|
|
||
|
|
||
| def test_oaconvolve_sdp_blocksize(): | ||
| from sdp.challenger_sdp import sliding_dot_product |
There was a problem hiding this comment.
This line needs to be modified if, at a later time, we decide to move the proposal to a new file (module).
@seanlaw |
There was a problem hiding this comment.
@NimaSarajpoor I've left some comments but would still like another pass after you've cleaned things up further
I do agree that, for the most part, things look clean. I think it still lacks clarity as to what is happening or why the logic is coded in this way
| Block size for the convolution. Will be at least `m` and at most `n`. | ||
| """ | ||
| if conv_block_size is None: | ||
| if m >= n / 2: |
There was a problem hiding this comment.
As I mentioned before, this is purely based on scipy's logic:
However, the reason is not clear to me.
There was a problem hiding this comment.
The overlap-add method adds the last m-1 elements of a block to the first m-1 elements of the next block. Therefore, if conv_block_size is at least 2 * (m-1), then the head and tail of each block will not have common elements and the current implementation works. If conv_block_size is less than 2 * (m-1), the current implementation fails. So: conv_block_size >= 2(m-1)
Also, note that conv_block_size should be <n. Otherwise, there is no point in splitting T into blocks.
Therefore: 2(m-1) <= conv_block_size < n , which gives: m < n/2 + 1
Note:
The current implementation shows conv_block_size = max(conv_block_size, m). However, as mentioned above, the sdp function fails if conv_block_size is < 2 * (m-1). So, we need to:
(1) use conv_block_size = max(conv_block_size, 2 * (m-1)) instead of conv_block_size = max(conv_block_size, m)
(2) Or, we need to revise the implementation so that it can handle cases where conv_block_size is < 2(m-1).
There was a problem hiding this comment.
Also: I submitted a question in stack overflow regarding the condition if m >= n / 2:
There was a problem hiding this comment.
The overlap-add method adds the last
m-1elements of a block to the firstm-1elements of the next block. Therefore, ifconv_block_sizeis at least2 * (m-1), then the head and tail of each block will not have common elements and the current implementation works.
If the condition conv_block_size < 2 * (m-1) is not met, the overlap-add approach should still work. See example below.
Example:
Let's compute the sliding dot product between T=[1, 2, 3, 4] and Q=[10, 20, 30]. The sliding dot product is: [140, 200].
The sliding dot product between T and Q is equivalent to the valid convolution between T and Qr, which is the reverse of Q. Let's use overlap-add method and set conv_block_size to m=len(Qr) == 3.
# Each block has zero-padding of length `m-1`
block1: 1, 0, 0
block2: 2, 0, 0
block3: 3, 0, 0
block4: 4, 0, 0
# reverse of Q
Qr = [30, 20, 10]
In overlap-add method, we compute the circular convolution between each block and Qr. We can use the flip-and-slide method. This gives:
out_block1: 30, 20, 10
out_block2: 60, 40, 20
out_block3: 90, 60, 30
out_block4: 120, 80, 40
We now add m-1 == 2 elements of each block to the first m-1 == 2 elements of next block.
out: out_block1 & out_blokc2 --> 30, 80, 50, 20
out: out & out_block3 --> 30, 80, 140, 80, 30
out: out & out_block4 --> 30, 80, 140, 200, 110, 40
Get the slice (m-1, n), which is (2, 4):
[140, 200]
So, the overlap-add method works if conv_block_size is set to m. The current implementation uses vectorized operation to perform the overlap-add between blocks. However, currently, the vectorized operation used in our implementation fails when conv_block_size is set to a value that is less than 2 * (m - 1).


This PR is to address #34.