>

Fortran 라이브러리 (BLAS/LAPACK)에 대한 SciPy 인터페이스 작업을 시작했습니다. SciPy 인터페이스와 Cython을 사용하여 BLAS/LAPACK에 직접 전화 하고 해결책을 찾았지만 numpy.zeros 를 사용해야했습니다.  실제로 포트란 코드를 직접 호출하면 속도가 향상됩니다. 문제는 Fortran 코드가 Numpy 버전 ( np.outer )과 일치하기 위해 0 값의 출력 매트릭스 (메모리의 내부 매트릭스에서 작동)가 필요하다는 것입니다 ).

그래서 파이썬의 1000x1000 제로 행렬이 8us (% timeit 또는 0.008ms 사용) 만 사용하기 때문에 조금 당황했습니다. 왜 Cython 코드를 추가하면 런타임이 메모리 뷰에서 생성되는지 알 수 있습니까? (기본적으로 1000 x 1000 행렬 곱셈에서는 3ms에서 8ms 정도입니다). 그런 다음 SO를 검색 한 후 memset 를 사용하여 다른 곳에서 해결책을 찾았습니다.  가장 빠른 어레이 변경 메커니즘으로 그래서 참조 된 게시물에서 최신 memoryview 까지 전체 코드를 다시 작성했습니다.  형식화하고 이와 같은 것을 얻었습니다 (Cython cyblas.pyx  파일) :

import cython
import numpy as np
cimport numpy as np
from libc.string cimport memset #faster than np.zeros
REAL = np.float64
ctypedef np.float64_t REAL_t
ctypedef np.uint64_t  INT_t
cdef int ONE = 1
cdef REAL_t ONEF = <REAL_t>1.0
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cpdef outer_prod(double[::1] _x, double[::1] _y, double[:, ::1] _output):
    cdef int M = _y.shape[0]
    cdef int N = _x.shape[0]
    memset(&_output[0,0], 0, M*N)
    with nogil:
        dger(&M, &N, &ONEF, &_y[0], &ONE, &_x[0], &ONE, &_output[0,0], &M)

테스트 스크립트

import numpy as np;
from cyblas import outer_prod;
a=np.random.randint(0,100, 1000);
b=np.random.randint(0,100, 1000);
a=a.astype(np.float64)
b=b.astype(np.float64)
cy_outer=np.zeros((a.shape[0],b.shape[0]));
np_outer=np.zeros((a.shape[0],b.shape[0]));
%timeit outer_prod(a,b, cy_outer)
%timeit np.outer(a,b, np_outer)

이로 인해 출력 매트릭스 값을 재설정하는 문제가 해결되었지만 여전히이 문제가있는 행 125 이후에만 해결되었습니다 (아래 해결 참조). 나는 memset 를 설정 생각  M * N에 대한 길이 매개 변수는 메모리에서 1000 * 1000을 지우지 만 분명히 그렇지 않습니다.

memset 를 사용하여 전체 출력 매트릭스를 0으로 재설정하는 방법에 대한 아이디어가 있습니까? ? 대단히 감사합니다.

  • 답변 # 1

    [업데이트-수정 사항 : M*N 의 어레이 크기뿐만 아니라 #bytes가 필요했습니다. 즉, M*N*variable_bytes  길이 입력으로. 논리는 이전 결과에서 볼 수 있습니다. 125 행은 * 8 바이트 = 1000 행이 중지 된 위치이므로 질문에 대답합니다. 여전히 100 개 루프, 루프 당 3 : 5.41ms (사이 톤) 최고 (100 개), 루프 당 3 : 3.95ms (최대 수) (최소)로 훌륭하지만 해결되었습니다. 위 코드를 변경하면 다음이 추가됩니다. cdef variable_bytes = np.dtype(REAL).itemsize #added to get bytes for memset, after REAL is defined, in this case 8 bytes 그런 다음 memset을 호출 할 때 : memset(&_output[0,0], 0, M*N*variable_bytes) # gives the same output as np.zeros function  지금 내가 볼 수있는 유일한 장소는 prange 를 사용하는 것입니다.  큰 행렬에 대한 OpenMP 문이지만 아직 보이지 않습니다.

  • 이전 ios - 뷰를 추가 한 직후에 UIView 애니메이션이 작동하지 않는 이유는 무엇입니까?
  • 다음 javascript - 클릭으로 레이어를 이동하는 방법