I wonder if it would help to decorate compute_mandelbrot with @numba.jit(parallel=True) and change your call to range to a numba.prange.
Ironically I’m going through this process at work this week to improve the performance of scipy.stats.ks_2samp
Ironically I’m going through this process at work this week to improve the performance of scipy.stats.ks_2samp
# guvectorize also supports target='parallel' for automatic parallelization
@numba.guvectorize([(complex128[:], uint8[:])], "(n)->(n)")
def compute_mandelbrot_gu(cs, out):
"compute number of iterations of z² + c before it escapes"
for i in range(cs.shape[0]):
c = cs[i]
z = 0j
count = 0
while count < 200:
z = z * z + c
if (z * z.conjugate()).real > 4.:
break
count += 1
out[i] = count
Whether to use numba's parallel for guvectorize or mine, it doesn't matter so much, they perform about the same. Parallelizing on a higher level is generally favorable to me.One thought here: the number of 100%+ improvements made here just underscores how slow python is to start with :). And yes, everyone in comments here complaining about numpy are sort of right, since the ultimate end here is just a flat loop without numpy, but as a numpy function.