2016-04-10 6 views
0

Ich habe ein Array, das die Summe der verschiedenen Dinge enthalten muss und daher möchte ich Reduktion für jedes seiner Elemente durchführen. Hier ist der Code:Reduktion von Array in Cython parallel

cdef int *a=<int *>malloc(sizeof(int) * 3) 
for i in range(3): 
    a[i]=1*i 
cdef int *b 
for i in prange(1000,nogil=True,num_threads=10): 
    b=res() #res returns an array initialized to 1s 
    with gil: #if commented this line gives erroneous results 
     for k in range(3): 
      a[k]+=b[k] 
for i in range(3): 
    print a[i] 

Bis es mit gil der Code ist in Ordnung läuft gibt sonst falsche Ergebnisse. Wie mit Reduzierungen auf jedem Element des Arrays zu behandeln, ohne Gil zu verwenden Ursache Gil ich denke, wird blockieren andere Threads

+0

Haben Sie 'cdef int k'? – Kevin

+0

@Kevin Ja, ich tat –

Antwort

1

Die Art und Weise Reduktionen in der Regel arbeiten, ist die Summe individuell für jeden Thread, und fügen Sie sie dann zusammen an der Ende. Sie könnten dies manuell mit etwas wie

cdef int *b 
cdef int *a_local # version of a that is duplicated by each thread 
cdef int i,j,k 

# set up as before 
cdef int *a=<int *>malloc(sizeof(int) * 3) 
for i in range(3): 
    a[i]=1*i 

# multithreaded from here 
with nogil, parallel(num_threads=10): 
    # setup and initialise a_local on each thread 
    a_local = <int*>malloc(sizeof(int)*3) 
    for k in range(3): 
     a_local[k] = 0 

    for i in prange(1000): 
     b=res() # Note - you never free b 
       # this is likely a memory leak.... 

     for j in range(3): 
      a_local[j]+=b[j] 

    # finally at the end add them all together. 
    # this needs to be done `with gil:` to avoid race conditions 
    # but it isn't a problem 
    # because it's only a small amount of work being done 
    with gil: 
     for k in range(3): 
      a[k] += a_local[k] 
    free(a_local) 
+0

Wie unterscheidet es sich von dem Beispiel, das ich gab? –

+0

'a_local' wird für jeden Thread erstellt und in der Hauptschleife aufsummiert, ohne das Gil zu verwenden (dies kann parallel passieren). Am Ende werden die 'a_local's für jeden Thread addiert. Dies erfordert die Gil, aber muss nur einmal pro Thread (statt einmal pro Schleife) passieren, also ist ein kleiner Preis. – DavidW

+0

Hab es ..... danke :) –