Эффективные математические операции на небольших массивах в Python с Cython - PullRequest
9 голосов
/ 19 марта 2011

Я использую numpexpr для быстрой математики на больших массивах, но если размер массива меньше размера кэша ЦП, написание моего кода на Cython с использованием простой математики для массива выполняется намного быстрее, особенно если функция вызывается несколько раз.

Вопрос в том, как вы работаете с массивами в Cython, или, более точно, существует ли прямой интерфейс к типу Python для array.array в Cython?Я хотел бы сделать что-то вроде этого (простой пример)

cpdef array[double] running_sum(array[double] arr):
    cdef int i 
    cdef int n = len(arr)
    cdef array[double] out = new_array_zeros(1.0, n)
    ... # some error checks
    out[0] = arr[0]
    for i in xrange(1,n-1):
        out[i] = out[i-1] + arr[i]

    return(out)

Сначала я попробовал использовать обертку Cython и работал с ndarrays, но кажется, что их создание очень дорого для небольших одномерных массивов, по сравнениюс созданием массива C с помощью malloc (но обработка памяти становится проблемой).

Спасибо!

1 Ответ

5 голосов
/ 30 марта 2011

Вы можете бросить свой простой с основными функциями, и проверки вот макет для начала:

from libc.stdlib cimport malloc,free

cpdef class SimpleArray:
    cdef double * handle
    cdef public int length
    def __init__(SimpleArray self, int n):
        self.handle = <double*>malloc(n * sizeof(double))
        self.length = n
    def __getitem__(self, int idx):
        if idx < self.length:
            return self.handle[idx]
        raise ValueError("Invalid Idx")
    def __dealloc__(SimpleArray self):
        free(self.handle) 

cpdef SimpleArray running_sum(SimpleArray arr):
    cdef int i 
    cdef SimpleArray out = SimpleArray(arr.length)

    out.handle[0] = arr.handle[0]
    for i from 1 < i < arr.length-1:
        out.handle[i] = out.handle[i-1] + arr.handle[i]
    return out

может использоваться как

>>> import test
>>> simple = test.SimpleArray(100)
>>> del simple
>>> test.running_sum(test.SimpleArray(100))
<test.SimpleArray object at 0x1002a90b0>
...