2017-06-21 40 views
0

我正在使用prange來修改數組。我努力以儘可能少的黃線儘可能由用Cython編譯器生成的HTML頁面:cython prange - 處理__Pyx_ErrFetchWithState/__Pyx_ErrRestoreWithState

cython function_prange.pyx -a 

但提取的陣列,以修改它的一部分的時候,我總是有這樣的代碼生成:

{ 
    #ifdef WITH_THREAD 
    PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); 
    #endif 
    #ifdef _OPENMP 
    #pragma omp flush(__pyx_parallel_exc_type) 
    #endif /* _OPENMP */ 
    if (!__pyx_parallel_exc_type) { 
     __Pyx_ErrFetchWithState(&__pyx_parallel_exc_type, &__pyx_parallel_exc_value, &__pyx_parallel_exc_tb); 
     __pyx_parallel_filename = __pyx_filename; __pyx_parallel_lineno = __pyx_lineno; __pyx_parallel_clineno = __pyx_clineno; 
     __Pyx_GOTREF(__pyx_parallel_exc_type); 
    } 
    #ifdef WITH_THREAD 
    PyGILState_Release(__pyx_gilstate_save); 
    #endif 
} 

是否有可能避免這些__Pyx_ErrFetchWithState/__Pyx_ErrRestoreWithState?真的有關係嗎?

在這裏的是,我使用的代碼:

第一功能添加雙對角線包含在大小爲一陣列的矩陣在function_nogil.pyx

import cython 

@cython.boundscheck(False) # turn off bounds-checking for entire function 
@cython.wraparound(False) # turn off negative index wrapping for entire function 
cdef void add_diag(double [:,:,:] a, int a_len, int a_wid, double coeff) nogil: 
    cdef int x_max = a_len 

    cdef int x 
    for x in xrange(x_max): 
     a[0,x,x] = a[0,x,x] + coeff 

及其在頭使用function_nogil.pxd

cdef void add_diag(double [:,:,:] a, int a_len, int a_wid, double coeff) nogil 

功能在function_prange.pyx

@cython.boundscheck(False) # turn off bounds-checking for entire function 
@cython.wraparound(False) # turn off negative index wrapping for entire function 
def prange_loop_idx(double [:,:,:] a, int a_dim1, int a_dim2, int a_dim3, double coeff,int num_threads): 

    cdef int i = 0 

    with nogil,parallel(num_threads=num_threads): 
     for i in prange(a_dim1): 
      add_diag(a[i:i+1:,],a_dim2,a_dim3,coeff) 

回答

1

這不是那麼糟糕,因爲它看起來。當您查看完整的C代碼時,您會看到這只是一個錯誤處理位代碼,只有在出現錯誤條件後纔會跳轉到goto執行。 (錯誤條件是它檢查內存視圖片的構造是否正確 - 我認爲這是使用片而不是單個索引的結果,例如將步設置爲0會觸發錯誤)。

所以,你有額外的錯誤檢查的一點點,可能不是絕對必要的,但我認爲明智的做法是息事寧人(我的電腦上它此行):

if (unlikely(__pyx_memoryview_slice_memviewslice(
    &__pyx_t_4, 
    __pyx_v_a.shape[0], __pyx_v_a.strides[0], __pyx_v_a.suboffsets[0], 
    0, 
    0, 
    &__pyx_t_5, 
    __pyx_v_i, 
    (__pyx_v_i + 1), 
    0, 
    1, 
    1, 
    0, 
    1) < 0)) 
{ 
    __PYX_ERR(0, 21, __pyx_L12_error) 
} 

但實際的代碼你擔心的是在正常操作中不被調用,所以幾乎沒有成本,你可以忽略。


我認爲parallelprange生成的代碼可能是非常複雜,生成的HTML文件不是在顯示你正確的位100%有用,這就是爲什麼你會看到它鏈接到行,但你沒有看到我上面顯示的錯誤檢查代碼。