Какой самый простой способ распараллелить рекурсивный код в Cython - PullRequest
3 голосов
/ 22 мая 2019

Рассмотрим рекурсивный код в Cython следующей универсальной формы:

cpdef function(list L1, list L2):
    global R
    cdef int i,n #...
    cdef list LL1,LL2 #...
    # ...
    # core of the code
    # ...
    n= #...
    for i in range(n):
        LL1= #...
        LL2= #...
        function(LL1,LL2)

Новое замечание : мой соответствующий код - просто исследование деревасобирая фрукты, все ветви независимы.Рассмотрим компьютер с несколькими ЦП. Я хотел бы распараллелить его следующим образом: каждый ЦП имеет свою очередь, когда код поступает на новый узел дерева, появляется несколько возможных новых дочерних элементов, и дочерний элемент выделяется ЦП с помощьюнаименьшая очередь.Кажется, это общий способ распараллеливания исследования дерева.

Вопрос : Какой самый простой способ реализовать такое распараллеливание?

Я пытался предшествовать моему коду from cython.parallel import prange, а затем заменить range(n) на prange(n), но я получил ошибку:

prange() can only be used without the GIL

Затем я заменил prange(n) на prange(n,nogil=True) но я получил много ошибок, таких как:

Assignment of Python object not allowed without gil
Coercion from Python not allowed without the GIL
Indexing Python object not allowed without gil
Calling gil-requiring function not allowed without gil

Ниже приведен соответствующий код, который я хочу распараллелить:

cpdef SmithFormIntegralPointsSuperFiltred(list L, list LL, list co, list A):
    global R,clp
    cdef int i,j,k,l,ll,p,a,c,cc,rc,m,f,b,z,zz,lp,s,la,kk,ccc,zo,jj,lM
    cdef list LB,S,P,CP,F,cco,PP,PPP,coo,V,LLP,LLPO,Mi,M
    m=10000
    l=len(L)
    ll=len(LL)
    la=len(A[0])
    z=0
    zz=0
    P=[]
    for i in range(l):
        if L[i]==-1:
            P.append(i)
    lp=len(P)
    if lp<clp:
        print([lp,L])
        clp=lp
    if lp==0:
        F=list(matrix(LL)*vector(L))
        b=0
        for f in F:
            if f<0:
                b=1
                break
        if b==0:    
            R.append(F); print(L)
    if lp>0:
        PP=[m for j in range(lp)]
        PPP=[[] for j in range(lp)]
        for i in range(ll):
            a=0
            for j in P:
                if LL[i][j]>0:
                    a+=1
                    if a==2:
                        break
            if a<=1:
                CP=list(set(range(l))-set(P))
                c=sum([LL[i][j]*L[j] for j in CP])
                if a==0 and c<0:
                    z=1
                    break
                if a==1 or (a==0 and c>=0):
                    LLPO=[LL[i][P[k]] for k in range(lp)]
                    for j in range(lp):
                        LLP=LLPO[:]
                        cc=-LLP[j]
                        if cc<>0:
                            del LLP[j]
                            if LLP==[0 for k in range(lp-1)]:
                                PPP[j].append(i)
                            zz=1
                            if cc>0:
                                rc=c/cc
                                if rc<PP[j]:
                                    PP[j]=rc
        if z==0 and zz==1:
            zo=0
            for i in range(lp):
                Mi=[]
                if PPP[i]<>[]:
                    for j in range(PP[i]+1):
                        ccc=0
                        coo=copy.deepcopy(co)
                        for k in PPP[i]:
                            s=sum([LL[k][kk]*L[kk] for kk in range(l)])+(j+1)*LL[k][P[i]]
                            V=A[k]
                            for kk in range(la):
                                if V[kk]<>0:
                                    if s>=0 and coo[kk][V[kk]]>=s:
                                        coo[kk][V[kk]]-=s
                                    else:
                                        ccc=1
                                        break
                            if ccc==1:
                                break
                        if ccc==0:
                            Mi.append(j)
                    if len(Mi)<m:
                        zo=1
                        m=len(Mi)
                        M=Mi
                        p=i
            if zo==1:
                M.reverse()
                lM=len(M)                                       
                for jj in range(lM):
                    j=M[jj]
                    cco=copy.deepcopy(co)
                    for k in PPP[p]:
                        s=sum([LL[k][kk]*L[kk] for kk in range(l)])+(j+1)*LL[k][P[p]]
                        V=A[k]
                        for kk in range(la):
                            if V[kk]<>0:
                                cco[kk][V[kk]]-=s
                    LB=L[:]
                    LB[P[p]]=j
                    SmithFormIntegralPointsSuperFiltred(LB,LL,cco,A)

Глобальные переменные R и clp не важны, я могу управлятьбез глобальной переменной, если необходимо.

...