2012-10-13 3 views
2

나는 cython을 사용하는 것에 관해서 많이 사용하고있는 함수를 빠르게하고 싶었다. 그러나 문서에서 찾을 수있는 가능한 모든 cython 최적화를 시도한 후에 cython 코드는 python + numpy 함수보다 약 6 배 더 느립니다. 실망!예기치 않게 속도가 느린 Cython화된 함수

이 내 테스트 코드입니다 : (forward1는 파이썬 함수, forward2 사이 썬 기능입니다)

#geometry.py 
def forward1(points, rotation, translation): 
    '''points are in columns''' 
    return np.dot(rotation, points - translation[:, np.newaxis]) 

#geometry.pyx 
import numpy as np 
cimport numpy as np 
cimport cython 

@cython.boundscheck(False) 
@cython.wraparound(False) 
@cython.nonecheck(False) 
cdef np.float64_t[:,:] forward2(np.float64_t[:,:] points, np.float64_t[:,:] rotation, np.float64_t[:] translation): 
    '''points are in columns''' 
    cdef unsigned int I, J 
    I = points.shape[0] 
    J = points.shape[1] 
    cdef np.float64_t[:,:] tmp = np.empty((I, J), dtype=np.float64) 
    cdef unsigned int i 
    for i in range(J): 
     tmp[0, i] = points[0, i] - translation[0]   
     tmp[1, i] = points[1, i] - translation[1]   
    cdef np.float64_t[:,:] result = np.dot(rotation, tmp) 
    return result 

def test_forward2(points, rotation, translation): 
    import timeit 
    cdef np.float64_t[:,:] points2 = points 
    cdef np.float64_t[:,:] rotation2 = rotation 
    cdef np.float64_t[:] translation2 = translation 
    t = timeit.Timer(lambda: forward2(points2, rotation2, translation2)) 
    print min(t.repeat(3, 10)) 

가 다음 내가 시간 : I가 할 수있는 일이

t = timeit.Timer(lambda: forward1(points, rotation, translation)) 
print min(t.repeat(3, 10)) 
0.000368164520751 

test_forward2(points, rotation, translation) 
0.0023365181969 

있는가 Cython 코드를 더 빨리 만들 수 있습니까?

forward1이 cython에서 빨라지지 않을 경우, 위브를 사용하여 속도를 향상시킬 수 있습니까?

편집 :

그냥 기록을 위해, 내가 기능을 속도를 시도한 또 다른 한가지는 내 포인트 컬럼에 저장되어있는 바와 같이, 포트란 위해 지점을 통과하고 꽤 몇 가지가 있습니다 그들. 또한 로컬 tmp를 포트란 순서로 정의합니다. 함수의 빼기 부분은 빠르지 만 numpy.dot는 C 순서 출력을 필요로한다고 생각합니다 (어쨌든이 문제를 해결하려면?). 따라서이 경우에도 속도가 향상되지 않습니다. 나는 또한 빼기 부분이 C 순서로 더 빠르도록 포인트를 조바꿈하려고 시도했지만, 내적 제품이 여전히 가장 비싼 부분 인 것으로 보입니다.

또한 numpy.dot가 C 순서인데도 memoryviews를 out 인수로 사용할 수 없다는 것을 알았습니까? 이것은 버그입니까?

+0

의 출력에서 ​​봐 가지고 사용하고 무엇을 찾으려면. 일반적으로 속도 향상을 위해 아무 것도 할 필요가 없습니다. – none

답변

4

그냥 코드로 보입니다. 배열 (array product)과 내적 (dot product)을 뺀 것입니다. numpy은 이미 매우 최적화되어 있습니다.

Cython은 numpy가 자주 실행되지 않는 경우를 빠르게 처리합니다 (예 : 반복이 파이썬으로 작성되는 반복 알고리즘).이 경우 내부 루프는 BLAS 라이브러리에 의해 이미 수행되고 있습니다.

속도를 높이려면 가장 먼저 BLAS/LAPACK/ATLAS/etc 라이브러리 numpy가 연결되어 있는지 확인해야합니다. 이와 같은 경우 튜닝 된 선형 대수 라이브러리 (예 : ATLAS 또는 Intel의 MKL)를 사용하면 큰 경우 (경우에 따라 10 배 이상) 차이가 발생합니다.

는 현재`numpy` 이미`계산 fortran` 라이브러리를`c`를 사용하고 numpy.show_config()

+0

괜찮습니다. 이해합니다. numpy.show_config()를 실행했지만 결과를 해석하는 방법을 모르겠다.
'mkl_info : libraries = [ 'mkl_lapack95', 'mkl_blas95', 'mkl_intel_c', ...] library_dirs = [ 'C :/Program Files (x86) /Intel/Compiler/11.1/070/mkl/ia32/lib '] define_macros = [('SCIPY_MKL_H ', 없음)] include_dirs = ['C :/Program Files (x86)/Intel /Compiler/11.1/070/mkl/include ']' lapack_opt_info, blas_opt_info, lapack_mkl_info 및 blas_mkl_info에 대해 비슷한 구조가 나타납니다 내 numpy 버전이 MKL에 연결되었다는 의미입니까? 또는 [('SCIPY_MKL_H', None)]은 그렇지 않다는 것을 의미합니까? – martinako

+0

그냥 레코드 용으로, 내 numpy 버전은 '1.6.2'이고 windows7 상자에 EPD 무료 배포판을 설치했습니다. – martinako

+0

예, 귀하의 numpy는 전년도 MKL에 링크되어 있습니다. 내 제안은 그다지 도움이되지 않습니다.MKL은 당신이 얻을 수있는만큼 최적화되어 있습니다. –

관련 문제