2

I was experimenting with Numba's @jit and @guvectorize and find that @guvectorize is considerably slower than @jit. For example, I have the following code that calculates the rolling moving average:

import numpy as np
from numba import *

@guvectorize(['void(float64[:], float64[:], float64[:])'], '(n),()->(n)')
def sma(x, m, y):
    n = x.shape[0]
    mi = int(m)
    y[:] *= np.nan
    for i in range(mi-1, n):
        for j in range(i-mi+1, i+1):
            y[i] = x[j] if j == i-m+1 else y[i]+x[j]
        y[i] /= double(mi)

@jit(float64[:](float64[:], float64))
def sma1(x, m):
    n = x.shape[0]
    mi = int(m)
    y = np.empty(x.shape[0]) * np.nan
    for i in range(mi-1, n):
        for j in range(i-mi+1, i+1):
            y[i] = x[j] if j == i-m+1 else y[i]+x[j]
        y[i] /= double(mi)
    return y

Here is the testing code:

import movavg_nb as mv1
import numpy as np
x = np.random.random(100)

import time as t

t0 = t.clock()
for i in range(10000):
    y = mv1.sma(x, 5)
print(t.clock()-t0)

t0 = t.clock()
for i in range(10000):
    y = mv1.sma1(x, 5)
print(t.clock()-t0)

I ran this twice, because Numba usually needs to assign types the first time. Here are the results of the testing code for the second time:

17.459737999999998  # corresponding to @guvectorize
0.036977999999997735  # corresponding to @jit

The order of magnitude is > 450x

Question: I can understand the purpose of @vectorize (where the inputs are the same), but what would be the purpose of @guvectorize when @jit is faster? (or it there something in my code that is slowing it?)

uday
  • 6,453
  • 13
  • 56
  • 94
  • Try running your code with a profiler: this may point you in the right direction. http://www.huyng.com/posts/python-performance-analysis/ may help... – boardrider Jun 28 '15 at 17:10
  • The prupose of @guvectorize is that you can pass things with more dimensions than specified and it applies it intellegently to the extra dimensions (e.g. try calling `mv1.sma` with two arrays and look at the shape of the output). I don't know about the speed though. – DavidW Jun 28 '15 at 17:44
  • I think the compiler chokes on the line `y[:] *= np.nan` and has to fall back to "object mode". In that case the compiled code is not much faster than normal Python loops. –  Jul 12 '15 at 16:59

0 Answers0