2017-10-11 6 views
2

배열을 읽고 배열을 반환하는 Cython 함수를 만들고 싶습니다. 이 함수는 파이썬 def 함수가 아니라 다른 cdef 함수 내에서 호출됩니다. 여기에 내가 가진 것이있다.Cython : 배열을 반환하는 C 함수를 만듭니다.

cdef inline int[:] array_test(double *x) nogil: 

    cdef int output[2] 
    output[0]=1 
    output[1]=9 

    return output 

하지만 컴파일 할 때, 나는 오류 얻을 : "작업을 길없이 사용할 수 없습니다"를 수있는 사람 내 .pyx 파일에서

cdef int[:] array_test(double *x) nogil 

: 내 .pxd 파일에서

도와주세요?

답변

3

아마 오해가 있습니다.이 함수는 c- 배열이지만 메모리보기 슬라이스를 반환하지 않습니다. 당신은 나를 믿을 필요가 없습니다. nogil을 삭제하고 cython을 호출하여이를 확인할 수 있습니다. 생성 된 * .c 인 파일에서는이 함수의 C-서명, __Pyx_memviewslice 중요한 부분이되고 볼 수 있습니다

static CYTHON_INLINE __Pyx_memviewslice __pyx_f_4file_array_test(CYTHON_UNUSED double *__pyx_v_x) 

이 메모리보기 파이썬 객체입니다, 그래서는 가비지 컬렉터에 등록해야하며, 따라서 Global Interpreter Lock이 필요합니다. 이것이 "Gil없이 허용되지 않는 작업"오류 메시지를 보는 이유입니다.

  1. "nogil"로 그것을 할 정말 그렇게 중요하다

    그래서 당신은 적어도 세 가지 옵션이 있습니다? 그렇지 않다면 그냥 버리십시오. 가장 간단한 솔루션 인 단점 : 성능이 저하 될 수 있습니다.

  2. 실제 C 배열을 사용하십시오 (예 : int *res = (int *) malloc(2*sizeof(int))). 그것은 빠르지 만, 단점 : 당신 스스로 메모리를 관리해야합니다.
  3. C++과 std::vector<int>을 사용하면 장점은 더 이상 메모리를 관리 할 필요가 없지만 C++로 전환해야한다는 것입니다.

가능성 (1)의 개선 (이 실제 코드 예제하지만, 힘에 대한 많은 차이를하지 않습니다) 만 필요 마지막 행을 위해 길을 aquire하는 것입니다

cdef inline int[:] array_test(double *x) nogil: 
    cdef int output[2] 
    output[0]=1 
    output[1]=9 
    with gil: 
     return output 

cdef inline void array_test(double *x, int[:] output) nogil: 
0 : 영업 이익은 제안함에 따라 는

, 추가 가능성에 함수의 서명을 변경하는 것

트릭 여기 : array_test은 더 이상 결과 메모리보기 슬라이스를 만들지 않으며 가비지 수집기에 등록 할 필요가 없으므로 "nogil"이 가능합니다.

array_test의 호출이 더 복잡해지고 호출자가 output 메모리보기를 만들기 위해 gil을 가져야하는 것처럼 약간의 단점이 있습니다. 그러나 호출자는 어떤 종류의 데이터 구조에서 결과를 저장해야하는지 (numpy 배열 또는 다른 것)를 결정할 수 있다는 이점도 있습니다.

+0

옵션을 제공해 주셔서 감사합니다. 문제를 회피 할 수있는 또 다른 방법은 함수를 무효화하고 추가 빈 입력 배열을 수정하는 것입니다. – user3433489

+0

@ user3433489 얼마나 간단합니까! 이걸 생각하지 않았어 ... – ead