Дополнительная типизация Cython и cimport для массива numpy замедляют производительность?

Ниже приведены два простых метода Cython, которые я написал. В методе g_cython() я использовал дополнительную типизацию для массива numpy a и b, но удивительно, что g_cython() в два раза медленнее, чем g_less_cython(). Интересно, почему это происходит? Я думал, что добавление этого сделает индексирование a и b намного быстрее?

PS. Я понимаю, что обе функции могут быть векторизованы в numpy - я просто изучаю приемы оптимизации cython.

import numpy as np; 
cimport numpy as np;

def g_cython(np.ndarray[np.int_t, ndim = 1] a, percentile):
    cdef int i
    cdef int n = len(a)
    cdef np.ndarray[np.int_t, ndim = 1] b = np.zeros(n, dtype = 'int')
    for i in xrange(n):
        b[i] = np.searchsorted(percentile, a[i])
    return b


def g_less_cython(a, percentile):
    cdef int i
    b = np.zeros_like(a)
    for i in xrange(len(a)):
        b[i] = np.searchsorted(percentile, a[i])
    return b

мой тестовый пример: len(a) == 1000000 и len(percentile) = 100

def main3():
    n = 100000
    a = np.random.random_integers(0,10000000,n)
    per = np.linspace(0, 10000000, 101)

    q = time.time()
    b = g_cython(a, per)
    q = time.time() - q
    print q

q = time.time()
bb = g_less_cython(a, per)
q = time.time() - q
print q

person Vendetta    schedule 03.01.2012    source источник
comment
Для меня ваш код не строится так, как написано - вам нужен импорт и cimport numpy, а в строке 4 вам нужно передать что-то вроде dtype=int в np.zeros, иначе он создает массив двойников (хотя, возможно, это зависит от версия cython?). Кроме того, было бы полезно, если бы вы предоставили типичный пример использования. В любом случае, если вы хотите сравнить, что делает cython в каждом случае, вы можете создать файл с помощью cython -a, который дает вам красиво отформатированный html-файл, в котором нажатие на строки кода python показывает соответствующий сгенерированный код C.   -  person James    schedule 03.01.2012
comment
@Джеймс Спасибо за ваш ответ. Я пропустил часть cimport и import, так как подумал, что размещение этих строк в коде будет отвлекать. Я добавил часть dtype.   -  person Vendetta    schedule 03.01.2012


Ответы (1)


Я проверил ваш код, g_cython немного быстрее, чем g_less_cython.

вот тестовый код

import pyximport; pyximport.install()
import search_sorted
import numpy as np
import time
x = np.arange(100000, dtype=np.int32)
y = np.random.randint(0, 100000, 100000)

start = time.clock()
search_sorted.g_cython(y, x)
print time.clock() - start

start = time.clock()
search_sorted.g_less_cython(y, x)
print time.clock() - start

вывод:

0.215430514708
0.259622599945

Я отключил граничную проверку и флаг переноса:

@cython.boundscheck(False)
@cython.wraparound(False)
def g_cython(np.ndarray[np.int_t, ndim = 1] a, percentile):
    ....

Разница не заметна, потому что вызов np.searchsorted(percentile, a[i]) является критической частью, которая использует большую часть ЦП.

person HYRY    schedule 05.01.2012
comment
Спасибо за ваш ответ. Даже для вашего тестового примера я все еще не получил ваших результатов. g_less_cython() еще быстрее. и я разместил свой тестовый пример. - person Vendetta; 05.01.2012
comment
кстати, какую платформу вы используете? Я не думал, что time.clock() обеспечивает большую точность? - person Vendetta; 05.01.2012
comment
Я использую Windows XP, time.clock() достаточно точен, docs.python.org/library/time.html?time.clock#time.clock - person HYRY; 06.01.2012