A jitted numba implementation with manual summation in a for loop is around ~100x faster. Using np.sum with slicing inside the numba function was only half as fast. This solution assumes that all slices are within valid bounds.
Generation of sufficiently large sample data for benchmarking
import numpy as np
import numba as nb
np.random.seed(42) # just for reproducibility
n, m = 5000, 100
a = np.random.rand(n,m)
bnd_l, bnd_r = np.sort(np.random.randint(m+1, size=(n,2))).T
Jitted with numba. Please make sure to benchmark compiled hot code by running the function at least twice.
@nb.njit
def slice_sum(a, bnd_l, bnd_r):
b = np.zeros(a.shape[0])
for j in range(a.shape[0]):
for i in range(bnd_l[j], bnd_r[j]):
b[j] += a[j,i]
return b
slice_sum(a, bnd_l, bnd_r)
Output
# %timeit 1000 loops, best of 5: 297 µs per loop
array([ 4.31060848, 35.90684722, 38.03820523, ..., 37.9578962 ,
3.61011028, 6.53631388])
With numpy inside a python loop (this is a nice, simple implementation)
b = np.zeros(n)
for j in range(n):
b[j] = np.sum(a[ j, bnd_l[j] : bnd_r[j] ])
b
Output
# %timeit 10 loops, best of 5: 29.2 ms per loop
array([ 4.31060848, 35.90684722, 38.03820523, ..., 37.9578962 ,
3.61011028, 6.53631388])
To verify the results are equal
np.testing.assert_allclose(slice_sum(a, bnd_l, bnd_r), b)
left_bnd[:]: right_bnd[:](why the use of[:]here?). Note also that the row slices will vary in length - another indication that compiled whole-array methods don't exist.