У меня есть модуль Cython:
#!python
#cython: language_level=3, boundscheck=False, nonecheck=False
import numpy as np
cimport numpy as np
def portfolio_s2( double[:,:] cv, double[:] weights ):
""" Calculate portfolio variance"""
cdef double s0
cdef double s1
cdef double s2
s0 = 0.0
for i in range( weights.shape[0] ):
s0 += weights[i]*weights[i]*cv[i,i]
s1 = 0.0
for i in range( weights.shape[0]-1 ):
s2 = 0.0
for j in range( i+1, weights.shape[0] ):
s2 += weights[j]*cv[i,j]
s1+= weights[i]*s2
return s0+2.0*s1
У меня есть эквивалентная функция в Numba:
@nb.jit( nopython=True )
def portfolio_s2( cv, weights ):
""" Calculate portfolio variance using numba """
s0 = 0.0
for i in range( weights.shape[0] ):
s0 += weights[i]*weights[i]*cv[i,i]
s1 = 0.0
for i in range( weights.shape[0]-1 ):
s2 = 0.0
for j in range( i+1, weights.shape[0] ):
s2 += weights[j]*cv[i,j]
s1+= weights[i]*s2
return s0+2.0*s1
Для ковариационной матрицы размера 10 версия Numba работает в 20 раз быстрее, чем Cython. Я предполагаю, что это связано с чем-то, что я делаю неправильно в Cython, но я новичок в Cython и не знаю, что делать.
Использование оптимизации Cel...
Я написал скрипт для проверки кода Cel против версии Numba:
sizes = [ 2, 3, 4, 6, 8, 12, 16, 32, 48, 64, 96, 128, 196, 256 ]
cython_timings = []
numba_timings = []
for size in sizes:
X = np.random.randn(100,size)
cv = np.cov( X, rowvar=0 )
w = np.ones( cv.shape[0] )
num_tests=10
pm.portfolio_s2( cv, w )
with Timer( 'Cython' ) as cython_timer:
for _ in range( num_tests ):
s2_cython = pm.portfolio_s2_opt( cv, w )
cython_timings.append( cython_timer.interval )
helpers.portfolio_s2( cv, w )
with Timer( 'Numba' ) as numba_timer:
for _ in range( num_tests ):
s2_numba = helpers.portfolio_s2( cv, w )
numba_timings.append( numba_timer.interval )
plt.plot( sizes, cython_timings, label='Cython' )
plt.plot( sizes, numba_timings, label='Numba' )
plt.title( 'Execution Time By Covariance Size' )
plt.legend()
plt.show()
Результирующая диаграмма выглядит следующим образом:
Диаграмма показывает, что для небольших ковариационных матриц Numba работает лучше. Но по мере увеличения размера ковариационной матрицы Cython лучше масштабируется и в конечном итоге превосходит его с большим отрывом.
Есть ли какие-то накладные расходы на вызов функций, из-за которых Cython имеет такую плохую производительность для небольших матриц? Мой вариант использования этого кода будет включать вычисление ковариаций для множества небольших матриц ковариаций. Поэтому мне нужна лучшая производительность для маленьких матриц, а не для больших.
i
не имеет статического типа. - person cel   schedule 29.03.2015cythonizing
кода и вообще не используя функцию. Обратите внимание, что вы обмениваете красивую структуру вашей программы на скорость. Я бы сделал это только в том случае, если вам действительно нужна эта дополнительная скорость. - person cel   schedule 30.03.2015