2015-03-26 11 views
5

Ich habe Array a der Größe N mit Zufallszahlen. OpenMP Verwenden Ich möchte die Elemente 0 bis 9 von b der Größe 10 in A. für jede Zahl Array erhöhen Die Sprache C istParallele Inkrementierung von Array-Elementen mit OpenMP

#pragma omp parallel for 
for(i = 0; i < N; i++) 
    b[a[i]]++; 

Leider gibt es offenbar Simultan schreibt in einigen Elementen von b und das Ergebnis ist nicht wie erwartet. Ich habe es versucht, indem ich b auf firstprivate und lastprivate gesetzt habe, aber das half auch nicht.

Die Aufgabe scheint einfach, aber ich weiß nicht, wie es geht, da es keine atomic für Arrays in OpenMP gibt. Ich könnte ein neues Array für die Anzahl der Threads erstellen und sie dann am Ende zusammenfügen, aber das scheint nicht optimal zu sein.

Welcher wäre der schnellste Weg, um das Auftreten der Zahlen in a in den Elementen des Arrays b zu zählen?

+2

Summe unabhängig und dann die Ergebnisse zusammenführen. –

+1

@BrianCain Ich bin mir nicht sicher, was Sie genau meinen. Mit "Summe" meinen Sie das Inkrement? Mit "unabhängig" meinen Sie, ich sollte eine neue private Variable erstellen? Mit Merge meinst du, ich sollte am Ende alle Versionen der privaten Variable aufaddieren? Weil das scheint mir ineffizient zu sein. Können Sie mir mit einem einfachen Codefragment zeigen, was Sie meinen? – Michael

+0

Der Algorithmus ist nicht so einfach wie ich angenommen hatte. Aber letztlich ist es ein Kompromiss und ob es funktioniert, hängt wahrscheinlich vom Verhältnis von N zu "b" Größe ab (ist es wirklich immer 10?). Eine einfachere Alternative besteht darin, eine Reihe von Mutexen zu verwenden. –

Antwort

0

Wenn einer der Werte in a [] identisch ist, würden Sie gleichzeitig in dasselbe Element von b schreiben.

a [0] = 1 und a [1] = 1 dann würden Sie gleichzeitig in b [1] schreiben.

0

Sie können 2 „für()“ eine Verwendung für jedes Array

+0

Dies sollte ein Kommentar sein – codingadventures

2

Ihre Frage, die ich fragte im Wesentlichen ein Duplikat einer Frage ist fill-histograms-in-parallel-with-openmp-without-using-a-critical-section.

Die einfache Lösung in Ihrem Fall ist

#pragma omp parallel 
{ 
    int i, b_local[10] = {0}; 
    #pragma omp for nowait 
    for(i = 0; i < n; i++) b_local[a[i]]++; 
    #pragma omp critical 
    for(i=0; i<10; i++) b[i] += b_local[i];  
} 

es möglich ist, dies ohne einen kritischen Abschnitt zu tun (meine Frage sehen), aber es ist nicht unbedingt effizienter.

Hier ist ein funktionierendes Beispiel

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

#define N 100 

void foo(int *b, int *a, int n) { 
    #pragma omp parallel 
    { 
     int i, b_local[10]; 
     memset(b_local, 0, 10*sizeof(int)); 
     #pragma omp for 
     for(i = 0; i < n; i++) b_local[a[i]]++; 


     #pragma omp critical 
     {  
      for(i=0; i<10; i++) { 
       b[i] += b_local[i]; 
      } 
     } 

    } 
} 

int main() { 
    int i; 
    int b[10] = {0,1,2,3,4,5,6,7,8,9}; 
    int b2[10] = {0,1,2,3,4,5,6,7,8,9}; 
    int a[N]; 
    for(i=0; i<N; i++) a[i] = rand()%10; 

    foo(b,a,N); 
    for(i=0; i<N; i++) b2[a[i]]++; 
    for(i=0; i<10; i++) printf("%d ", b[i]); puts(""); 
    for(i=0; i<10; i++) printf("%d ", b2[i]); puts(""); 
}