In [1]:
%load_ext cython

Plain Cython functions: compare cdef & cpdef


In [2]:
%%cython
# cython: boundscheck=False
# cython: cdivision=True

cpdef long f1(long x, long y):
    return x % y
        
cdef long f2(long x, long y):
    return x % y
        
def pyf1(long[:] x, long[:] y):
    cdef long result = 0
    for i in range(x.shape[0]):
        result += f1(x[i], y[i])
    return result
    
def pyf2(long[:] x, long[:] y):
    cdef long result = 0
    for i in range(x.shape[0]):
        result += f2(x[i], y[i])
    return result

Make some arrays of integers


In [3]:
import numpy
x = numpy.random.randint(1, 100, 2**20)
y = numpy.random.randint(1, 100, 2**20)
print(x[:5])


[66 31 26 99 80]

Compare cdef & cpdef


In [4]:
%timeit pyf1(x, y)
%timeit pyf2(x, y)


100 loops, best of 3: 8.15 ms per loop
100 loops, best of 3: 8.77 ms per loop

Same code, but as cdef class methods


In [5]:
%%cython
# cython: boundscheck=False
# cython: cdivision=True

cdef class A:
    cpdef long f1(self, long x, long y):
        return x % y

    cdef long f2(self, long x, long y):
        return x % y

    def pyf1(self, long[:] x, long[:] y):
        cdef long result = 0
        for i in range(x.shape[0]):
            result += self.f1(x[i], y[i])
        return result

    def pyf2(self, long[:] x, long[:] y):
        cdef long result = 0
        for i in range(x.shape[0]):
            result += self.f2(x[i], y[i])
        return result

Compare cdef & cpdef methods


In [6]:
obj = A()
%timeit obj.pyf1(x, y)
%timeit obj.pyf2(x, y)


100 loops, best of 3: 13.4 ms per loop
100 loops, best of 3: 9.85 ms per loop

...but you can "inline" a cdef method:


In [7]:
%%cython
# cython: boundscheck=False
# cython: cdivision=True

cdef class A:
    cpdef long f1(self, long x, long y):
        return x % y

    cdef long f2(self, long x, long y):
        return x % y
    
    cdef inline long f3(self, long x, long y):
        return x % y

    def pyf1(self, long[:] x, long[:] y):
        cdef long result = 0
        for i in range(x.shape[0]):
            result += self.f1(x[i], y[i])
        return result

    def pyf2(self, long[:] x, long[:] y):
        cdef long result = 0
        for i in range(x.shape[0]):
            result += self.f2(x[i], y[i])
        return result

    def pyf3(self, long[:] x, long[:] y):
        cdef long result = 0
        for i in range(x.shape[0]):
            result += self.f3(x[i], y[i])
        return result

In [8]:
obj = A()
%timeit obj.pyf1(x, y)
%timeit obj.pyf2(x, y)
%timeit obj.pyf3(x, y)


100 loops, best of 3: 13.1 ms per loop
100 loops, best of 3: 10.3 ms per loop
100 loops, best of 3: 8.83 ms per loop

In [ ]: