Optimizing many element-wise Numpy calls on small arrays

225 views
Skip to first unread message

erict...@u.northwestern.edu

unread,
Apr 11, 2017, 11:43:09 AM4/11/17
to cython-users
Hi all,

I have some Python code that uses lots of loops, which sounds perfect for optimization with Cython. However, I'm also heavily relying on Numpy to do element-wise operations (like addition, elementwise multiplication, sums, etc),  and numpy.random.choice. As I understand it, calling anything from Numpy results in a small overhead, which is negligible for fewer Numpy function calls and large arrays, but my scenario is the exact opposite. As a result, my run time went from ~24s in pure Python to 42s in Cython. 

Should I be using something like GSL to completely avoid the Python overhead? 

Thanks. 

Ian Bell

unread,
Apr 11, 2017, 8:26:10 PM4/11/17
to cython...@googlegroups.com
You might be interested in my cython wiki entry: https://github.com/cython/cython/wiki/ListExample and some similar code in my project that is even faster (the arraym class): https://github.com/ibell/pdsim/blob/master/PDSim/misc/datatypes.pyx

--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Robert Bradshaw

unread,
Apr 11, 2017, 11:06:09 PM4/11/17
to cython...@googlegroups.com
With Cython's buffer/memoryview syntax
http://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html
you can achieve numpy-like performance with elementwise loops (unlike
Python) which could be a saving here (especially if you can avoid
intermediates). Regardless, it should not be strictly slower than
Python. I'd be curious to see some example code.
>> email to cython-users...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "cython-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to cython-users...@googlegroups.com.

erict...@u.northwestern.edu

unread,
Apr 12, 2017, 12:17:10 AM4/12/17
to cython-users
Not sure if I'm doing something wrong here, but it seems Numpy is slowest. I'm still a beginner at this, so please let me know if I'm doing something wrong or inefficient. 

import numpy as np
cimport numpy as np
cimport cython
from libc.math cimport pow
from math import pow as pypow


# using np.power
def run():
    cdef int i
    cdef double[:] result = np.empty(20, dtype=np.double)
    cdef double[:] r_array = np.random.rand(20)

    for i in range(20000):
        result = np.power(r_array, 1.5)

    return result

# using pow() from libc.math
def pure_run():
    cdef unsigned int i, j
    cdef double[:] result = np.empty(20, dtype=np.double)
    cdef double[:] r_array = np.random.rand(20)

    for i in range(20000):
        for j in range(20):
            result[j] = pow(r_array[j], 1.5)

    return result

# using python's pow()
def py_run():
    cdef int i, j
    cdef double[:] result = np.empty(20, dtype=np.double)
    cdef double[:] r_array = np.random.rand(20)

    for i in range(20000):
        for j in range(20):
            result[j] = pypow(r_array[j], 1.5)

    return result


The results are as follows: 

Numpy: 2.62s
pow() from libc.math: 0.377s
pow() from Python: 1.70s

I determined these times by running the function 20 times using timeit.timeit().
Reply all
Reply to author
Forward
0 new messages