I need to create a (w,N)-matrix that looks like this:
w//2............N-1,N-1
. \ N-1
. \ N-1
. \ N-1
1...............N-1,N-1
0...................N-1
00..................N-2
. \ N-3
. \ .
. \ .
000000..............N-w//2
Which is an (w,N) matrix, with an odd w. The middle row is the range from 0 to N. For each row index above the middle row, the row is shifted to the left like with scipy.ndimage.shift(mode='nearest') and for each row below the middle row it is shifted to the right with the same method.
N is usually around 10^4 and w is usually between 10 and 10^2.
I've come up with 2 ways to do this:
from scipy.ndimage import shift
middle = np.arange(0, N)
final = np.vstack(
[shift(middle, i, mode='nearest') for i in range(-w//2, 0)] +
[middle] +
[shift(middle, i, mode='nearest') for i in range(1, w//2)] )
Which takes 0.035 seconds to run.
np.vstack([
np.maximum(
0,
np.minimum(
N-1,
np.arange(-step, N-step)
)
)
for step in range(-w//2, w//2)
])
Which takes 0.021 seconds to run.
These numbers were with N=10^3 and w=21.
I'd really like to get these numbers down as low as possible, ideally down to around 1ms.
I tried multiprocessing, but that doesn't really help, the overhead to too big to gain something from the concurrency. Also I know I could store this result somewhere, but that'd require a significant change by the caller of this function, so that'll be done later.
Is there any mathematical relation that can represent a tilt/shift operation like this? I couldn't think of one, but if there is, numpy can probably take advantage of that to beat my results.
So yeah, any ideas to make my code faster?