2013-03-12 2 views
2

У меня есть функция, которая вычисляет матрицу для меня, но она очень медленная. Даже в cython он работает медленно, поэтому мне было интересно, можно ли что-либо сделать для улучшения кода ниже.Эффективный способ создания матрицы с помощью cython

EDIT: Я изменил или добавил

des = np.zeros([n-m+1,m]) к cdef np.ndarray des = np.zeros([n-m+1,m], dtype=DTYPE) (Это быстрее, чем np.empty... Вместо того чтобы сказать m/2 я добавил cdef int m2 = m/2, но это не казалось, чтобы помочь что-нибудь

cimport numpy as np 
cimport cython 

DTYPE = float 
ctypedef np.float_t DTYPE_t 

@cython.boundscheck(False) 
@cython.cdivision(True) 
@cython.wraparound(False) 
cpdef map4(np.ndarray[DTYPE_t, ndim=1] s, int m): 

    cdef int n = len(s) 
    cdef int i 
    cdef int j 

    des = np.zeros([n-m+1,m]) 
    for j in xrange(m): 
     for i in xrange(m/2,n-m/2-1): 
      des[i-m/2,j] = s[i-j+m/2] 

    return des, s, m, n 
.

Обычно n~10000 и m=1001

+0

не забудьте проверить выходные данные 'cython -a' для деталей. Сгенерированный html-файл чрезвычайно полезен для просмотра слабых мест в коде – dmytro

+0

Да, html-файл действительно полезен, когда вы хотите увидеть медленную часть (или часть, которая требует большого количества преобразований), но это действительно не так очень полезно, если вы не знаете, как это сделать дальше. Но я согласен с тобой. Я также начал работу с html-файлом. –

+0

Кажется, вы просто храните простые кусочки массива 's'. Вы могли бы просто нарезать '' ', когда вам нужно? – 2013-09-19 23:45:59

ответ

3

Try:.

cdef np.ndarray des = np.zeros([n-m+1,m]) 

Вы также можете сделать это более конкретным, как и для параметра s. Вы также можете отключить проверку границ. Проверьте cython numpy tutorial.

Вы также можете захотеть сделать переменную:

cdef int m_2 = m/2 

и использовать его везде, где вы есть m/2, потому что я не знаю, если Cython будет делать, что оптимизация для вас.

+1

Вместо tmp var m_2 может быть предпочтительнее сказать 'for i в xrange (nm):'/'des [i, j] = s [i-j + m]' и/или срез массива –

+0

Я предполагаю, немного опоздать на вечеринку, но вы действительно должны добавить '[DTYPE_t, ndim = 2]' к объявлению статического типа 'des' (~ 10x speedup). Кроме того, замена 2-х-петель помогает немного, путем выравнивания доступа к массиву с макетом памяти. Это обеспечило время работы до 158 мс в моей системе с 2,45 секунды для исходного кода. – 2013-09-19 21:46:06

2

Это также может помочь использовать np.empty вместо np.zeros, если вы будете присвоить каждый элемент:

des = np.empty([n-m+1,m]) 
+0

Я обнаружил, что 'np.empty' не был самым быстрым выбором. –

+0

Хм, интересно, почему – askewchan

+0

Я нашел это очень полезным. Уменьшает время работы от 158 мс до 113 мс! – 2013-09-19 23:41:19

0

Я не вижу м быть установлены в любом месте. В нижней части кода вы указываете, что n ~ 10000 и m = 1001. Означает ли это, что m является постоянным целым числом в 32 бита? Не видя ваших флагов компиляции, часто стоит попробовать и без -ffast-math посмотреть, не изменилось ли это. При использовании больших массивов и матриц использование меньшего типа данных обычно показывает значительное ускорение при условии, что меньший тип данных сохраняет диапазон и точность, которые необходимы вашей программе, хотя я не вижу большой потенциальной выгоды от этого расчета.

Если вы можете показать нам код C, который сгенерирован этим, это может помочь.

Смежные вопросы