PCamargo
PCamargo

Reputation: 593

Why is this code slower in Cython than in Python?

I'm starting to learn Cython because of performance issues. This particular code is an attempt to implement some new algorithms in the transportation modeling (for planning) area.

I decided to start with a very simple function that I will use a LOT (hundreds of millions of times) and would definitely benefit from a performance increase.

I implemented this function in three different ways and tested them for the same parameter (for the sake of simplicity) for 10 million times each:

The cython code is this:

def BPR2(vol, cap, al, be):
    con=al*pow(vol/cap,be)
    return con


def func (float volume, float capacity,float alfa,float beta):
    cdef float congest
    congest=alfa*pow(volume/capacity,beta)
    return congest

And the script for testing is this:

agora=clock()
for i in range(10000000):
    q=linkdelay.BPR2(10,5,0.15,4)

agora=clock()-agora
print agora

agora=clock()
for i in range(10000000):
    q=linkdelay.func(10,5,0.15,4)
    
agora=clock()-agora
print agora

agora=clock()
for i in range(10000000):
    q=0.15*pow(10/5,4)
    
agora=clock()-agora
print agora

I'm aware of issues like transcendental functions (power) being slower, but I dont think it should be a problem.

Since there is an overhead for looking for the function on the function space, would it help the performance if I passed an array for the function and got an array back? Can I return an array using a function written in Cython?

For reference, I'm using:

Upvotes: 16

Views: 7695

Answers (3)

user1277476
user1277476

Reputation: 2909

When Cython is slower, it's probably due to type conversions, and possibly exacerbated by a lack of type annotations. Also, if you use C datastructures in Cython, that'll tend to be faster than using Python datastructures in Cython.

I did a performance comparison between CPython 2.x (with and without Cython, with and without psyco), CPython 3.x (with and without Cython), Pypy, and Jython. Pypy was by far the fastest, at least for the micro-benchmark examined: http://stromberg.dnsalias.org/~strombrg/backshift/documentation/performance/

Upvotes: 1

Kassym Dorsel
Kassym Dorsel

Reputation: 4843

Testing was done using :

for i in range(10000000):
  func(2.7,2.3,2.4,i)

Here are the results:

cdef float func(float v, float c, float a, float b):
  return a * (v/c) ** b
#=> 0.85

cpdef float func(float v, float c, float a, float b):
  return a * (v/c) ** b
#=> 0.84

def func(v,c,a,b):
  return a * pow(v/c,b)
#=> 3.41

cdef float func(float v, float c, float a, float b):
  return a * pow(v/c, b)
#=> 2.35

For highest efficiency you need to define the function in C and make the return type static.

Upvotes: 3

C0deH4cker
C0deH4cker

Reputation: 4075

This function could be optimized as such (in both python and cython, removing the intermediate variable is faster):

def func(float volume, float capacity, float alfa,f loat beta):
    return alfa * pow(volume / capacity, beta)

Upvotes: 1

Related Questions