简体   繁体   中英

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:

  • Cython code in a cython module. Running time: 3.35s

  • Python code in a Cython module. Running time: 4.88s

  • Python code on the main script. Running time: 2.98s

    As you can see, the cython code was 45% slower than the python code in a cython module and 64% slower than the code written on the main script. How is that possible? Where am I making a mistake?

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:

  • Windows 7 64bits
  • Python 2.7.3 64 Bits
  • Cython 0.16 64 Bits
  • Windows Visual Studio 2008

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.

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)

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/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM