[英]Using openMP with Cython: parallelising an inner loop
(如您所見,我對Python GIL和IN PYTHON(或cython)中的多線程等概念不是很熟悉)
我在Cython中編寫了一個函數,該函數由帶有double for循環的代碼片段組成,其中重復調用函數f。
for i in range(I):
for j in range(J):
res=f(A[i],B[j])
我有一台具有4個CPU內核的機器,我想並行化的不是第一個循環,而是第二個循環。 我找到了這個很棒的網站,但它不處理內部循環的情況,也不做詳細介紹。 所以我認為我可以寫:
for i in range(I):
#In what case can I release the GIL safely ? Is that necessary at all ?
with nogil, parallel(num_threads=4):
for j in prange(J,shedule="dynamic"):
res=f(A[i],B[j])
那行得通嗎? 我是否必須將with nogil放在這兩個循環之外,以免它反復出現在其中,從而釋放並“捕獲”該GIL東西? 有人可以向我解釋編寫此類語句背后的邏輯是什么,以及邏輯是什么,以便使我能夠泛化為未發現的問題。
釋放和重新捕獲GIL會花費時間,而建立並行循環也會花費時間。 因此,通常最好將最外面的循環設為並行循環。 但是,如果您有充分的理由特別希望並行化內部循環,則它可以工作,並且希望與f
包含的實際工作相比,其成本應該很小。
釋放GIL會阻止您訪問Python變量和調用Python函數。 鍵入Cython變量, cdef
函數和Cython內存視圖可以正常工作。 盡量with nogil:
加快速度。 因此,如果可能,請將其放在外部循環周圍,但如果不可能,則可以在其中顯示出來。
有必要釋放到GIL進行prange
循環。 如有必要,您可以在循環內部( with gil
)將其回收,但是嘗試僅在循環的一小部分並且僅在需要時才這樣做(需要GIL的代碼不能與需要GIL的其他代碼並行運行) 。
對於並行代碼,行res=f(A[i],B[j])
有點奇怪,因為僅會保存來自最后一個循環的res
。 通常,您會寫入數組的元素(例如res[i,j]=f(A[i],B[j])
)。 但是,這樣做可能有充分的理由,就像您展示的那樣...
如果您嘗試執行需要GIL的操作,Cython通常會警告您,因此最好嘗試一下。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.