2013-07-23 21 views
2

使用C++ 11我一直在使用以下模式來實現具有並行迭代器的圖數據結構。節點只是索引,邊是臨近數據結構中的條目。爲遍歷所有節點,函數(lambda,closure ...)被傳遞給一個parallelForNodes方法,並以每個節點作爲參數進行調用。迭代細節很好地封裝在方法中。我可以在Cython上使用這個並行迭代器模式嗎?

現在我想嘗試與Cython相同的概念。 Cython提供了cython.parallel.prange函數,該函數使用OpenMP來並行化一個範圍內的循環。爲了平行工作,需要使用參數nogil=True來禁用Python的全局解釋器鎖。沒有GIL,就不允許使用Python對象,這使得這個技巧變得棘手。

在Cython中可以使用這種方法嗎?

class Graph: 

    def __init__(self, n=0): 
     self.n = n 
     self.m = 0 
     self.z = n # max node id 
     self.adja = [[] for i in range(self.z)] 
     self.deg = [0 for i in range(self.z)] 

    def forNodes(self, handle): 
     for u in range(self.z): 
      handle(u) 

    def parallelForNodes(self, handle): 
     # first attempt which will fail... 
     for u in prange(self.z, nogil=True): 
      handle(u) 


# usage 

def initialize(u): 
    nonlocal ls 
    ls[u] = 1 

G.parallelForNodes(initialize) 

回答

0

首先,事物不能是沒有GIL的Python對象。

from cython.parallel import prange 

cdef class Graph: 
    cdef int n, m, z 

    def __cinit__(self, int n=0): 
     self.z = n # max node id 

    cdef void parallelForNodes(self, void (*handle)(int) nogil) nogil: 
     cdef int u 
     for u in prange(self.z, nogil=True): 
      handle(u) 

最大的漁獲有我們的函數指針是nogil

parallelForNodes本身不一定是nogil,但沒有理由不這樣做。

然後,我們需要一個ç函數來調用:

cdef int[100] ls 
cdef void initialize(int u) nogil: 
    global ls 
    ls[u] = 1 

,它就可以工作!

Graph(100).parallelForNodes(initialize) 

# Print it! 
cdef int[:] ls_ = ls 
print(list(ls_)) 
相關問題