Reputation: 119
This is my code:
@numba.jit( )
def dis4(x1,x2):
s=0.0
for i in range(len(x1)):
s+=(x1[i]-x2[i])**2
return math.sqrt(s)
x1=[random.random() for _ in range(m)]
x2=[random.random() for _ in range(m)]
%timeit dis4(x1,x2)
3.32 ms ± 37.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In contrast, it will be faster without jit
.
137 µs ± 1.62 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Upvotes: 1
Views: 1646
Reputation: 152715
It's slower because numba (silently) copied the lists.
To understand why this happens you need to know that numba has object-mode and nopython-mode. In object mode it can operate on Python data structures, however it will not be much faster than a normal Python function or even be slower (at least in general, there are very rare exceptions). In nopython-mode numba cannot operate on Python data-structures like list
, so in order for list
s to work it has to use a non-Python list. To create such a non-Python list (it's called a reflected list) from a Python list it has to copy and convert the lists contents.
This copy and conversion is what makes it much slower in your case.
That's also the reason why one generally should avoid using non-arrays arguments or returns with numba functions. The content of arrays doesn't need to be converted, at least if the dtype of the array is supported by numba so these are "safe".
If these data-structures (lists, tuples, sets) are confined within numba they are fine - however when these cross the numba⭤ Python boundary they have to be copied which (almost) always nullifies all the performance gains.
Just to show how the function performs with arrays:
import math
import random
import numba as nb
import numpy as np
def dis4_plain(x1,x2):
s=0.0
for i in range(len(x1)):
s+=(x1[i]-x2[i])**2
return math.sqrt(s)
@nb.jit
def dis4(x1,x2):
s=0.0
for i in range(len(x1)):
s+=(x1[i]-x2[i])**2
return math.sqrt(s)
m = 10_000
x1 = [random.random() for _ in range(m)]
x2 = [random.random() for _ in range(m)]
a1 = np.array(x1)
a2 = np.array(x2)
Timing:
dis4(x1, x2)
dis4(a1, a2)
%timeit dis4_plain(x1, x2)
# 2.71 ms ± 178 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit dis4(x1, x2)
# 24.1 ms ± 279 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit dis4(a1, a2)
# 14 µs ± 608 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
So while it's 10 times slower with lists and the numba.jit
, the jitted function with arrays is almost 200 times faster than the Python function with lists.
Upvotes: 1