I asked related questions on this stack last week, trying to isolate things I didn't understand about using the @jit decorator with Numba in Python. However, I hit the wall, so I just write the whole problem.
The problem is calculating the minimum distance between pairs of large segments. Segments are represented by their start and end points in 3D. Mathematically, each segment is parameterized as [AB] = A + (BA) * s, where s is in [0,1], and A and B are the beginning and end points of the segment. For two such segments, you can calculate the minimum distance and get the formula here .
I already uncovered this problem in another thread, and the answer was to replace the double loops of my code by vectorizing the problem, which, however, would affect memory problems for large sets of segments. So I decided to stick with loops and use numba jit instead.
Since many point products are required to solve the problem, and the numpy dot product is not supported by numba , I started by implementing my own three-dimensional point product.
import numpy as np from numba import jit, autojit, double, float64, float32, void, int32 def my_dot(a,b): res = a[0]*b[0]+a[1]*b[1]+a[2]*b[2] return res dot_jit = jit(double(double[:], double[:]))(my_dot) #I know, it not of much use here.
The function that calculates the minimum distance of all pairs in N segments takes Nx6 as an input array (6 coordinates)
def compute_stuff(array_to_compute): N = len(array_to_compute) con_mat = np.zeros((N,N)) for i in range(N): for j in range(i+1,N): p0 = array_to_compute[i,0:3] p1 = array_to_compute[i,3:6] q0 = array_to_compute[j,0:3] q1 = array_to_compute[j,3:6] s = ( dot_jit((p1-p0),(q1-q0))*dot_jit((q1-q0),(p0-q0)) - dot_jit((q1-q0),(q1-q0))*dot_jit((p1-p0),(p0-q0)))/( dot_jit((p1-p0),(p1-p0))*dot_jit((q1-q0),(q1-q0)) - dot_jit((p1-p0),(q1-q0))**2 ) t = ( dot_jit((p1-p0),(p1-p0))*dot_jit((q1-q0),(p0-q0)) -dot_jit((p1-p0),(q1-q0))*dot_jit((p1-p0),(p0-q0)))/( dot_jit((p1-p0),(p1-p0))*dot_jit((q1-q0),(q1-q0)) - dot_jit((p1-p0),(q1-q0))**2 ) con_mat[i,j] = np.sum( (p0+(p1-p0)*s-(q0+(q1-q0)*t))**2 ) return con_mat fast_compute_stuff = jit(double[:,:](double[:,:]))(compute_stuff)
So, compute_stuff (arg) takes 2D np.array (double [:,:]) as an argument, performs a bunch of operations with numba support (?) And returns another 2D np.array (double [:,:]). Nevertheless,
v = np.random.random( (100,6) ) %timeit compute_stuff(v) %timeit fast_compute_stuff(v)
I get 134 and 123 ms per cycle. Can you shed some light on why I cannot speed up my work? Any feedback would be highly appreciated.