I have to write a small simulation in cython, which is usually accelerated with numba. But I have to make this transition, since numba didn't support a scipy function which I wanted to use for modifying the function.
So essentially I have translated my simulation program into cython, which makes everything super slow compared to numba. So maybe there is a bottleneck in my cython code which i do not see.
My cython code:
import numpy as np
cimport numpy as cnp
cimport cython
cnp.import_array()
@cython.boundscheck(False)
@cython.wraparound(False)
def simulation(int N=10000, int N_save=10000):
cdef cnp.ndarray[double] x = np.empty(N_save, dtype=np.double)
cdef cnp.ndarray[double] r = np.random.standard_normal(size=N_save)
cdef fs = int(N / N_save)
cdef xold = 0
x[0] = 0
for i in range(1, N):
if i%N_save == 0:
r = np.random.standard_normal(size=N_save)
xnew = xold + r[i%N_save]
if (i % fs) == 0:
x[int(i / fs)] = xnew
xold = xnew
return x
The code I use for compilation:
from setuptools import setup
from Cython.Build import cythonize
import numpy as np
setup(
ext_modules=cythonize(
"test.pyx",
compiler_directives={'language_level' : "3"},
),
include_dirs=[np.get_include()]
)
The same code accelerated with numba:
@nb.jit(nopython=True, fastmath=True)
def simulation_nb(N=10000, N_save=10000):
x = np.zeros(N_save)
r = np.random.standard_normal(size=N_save)
fs = int(N / N_save)
xold = 0
x[0] = 0
for i in range(1, N):
if i%N_save == 0:
r = np.random.standard_normal(size=N_save)
xnew = xold + r[i%N_save]
if (i % fs) == 0:
x[int(i / fs)] = xnew
xold = xnew
return x
The Benchmark results with simulation(N=1000000, N_save=10000)
:
- Cython: 183ms
- Numba : 31.4ms
- Raw Python: 217ms
Why is my cython code almost as slow as the raw python alternative?
cython -a
will produce an annotated html file that'll give you a clue about what might be inefficient – Reptile