2015-04-14 14 views
5

Ich versuche, meine eigene Reduktion für Vektoren des Komplexes <float>, nach this answer auf die Frage Reducing on array in OpenMP zu definieren.Benutzerdefinierte Reduktion auf Vektor unterschiedlicher Größe

Aber die Größe meiner Vektoren sind nicht zur Kompilierzeit festgelegt, so dass ich nicht sicher bin, wie Sie den Initialisierer für den Vektor im Pragma declare reduction definieren. Das heißt, ich kann nicht einfach haben

initializer(omp_priv=TComplexVector(10,0)) 

Aber der Initialisierer wird für Vektoren benötigt.

Wie kann ich die Initializerklausel die Größe des Vektors, den ich zur Laufzeit brauche, übergeben? Was ich bis jetzt haben, ist unten:

typedef std::vector<complex<float>> TCmplxVec; 

void ComplexAdd(TCmplxVec & x,TCmplxVec & y){ 
    for (int i=0;i<x.size();i++) 
    { 
     x.real()+= y.real(); 
     //... same for imaginary part and other operations 
    } 

} 

#pragma omp declare reduction(AddCmplx: TCmplxVec: \ 
ComplexAdd(&omp_out, &omp_in)) initializer(\ 
omp_priv={TCmplxVec(**here I want a variable length**,0}) 

void DoSomeOperation() 
{ 
    //TCmplxVec vec is empty and anotherVec not 

    //so each thread runs the inner loop serially 
    #pragma omp parallel for reduction(AddCmplx: vec) 
    for (n=0 ; n<10 ; ++n) 
    { 
     for (m=0; m<=someLength; ++m){ 
     vec[m] += anotherVec[m+someOffset dependend on n and else]; 
     } 
    } 
} 
+1

Ihre Frage klingt wie ich interessant sein könnte, aber ich weiß, gibt es wirklich nicht, was du bist fragend. Sie benötigen mehr Code weniger Wörter und der Code muss allgemein sein und sollte keine Details enthalten, von denen Sie wahrscheinlich wissen werden. –

+0

Geben Sie Ihrer eigenen Länge statt 'int S_private [10] = {0};' do 'int * S_private = new int [n]()' und dann nach dem kritischen Abschnitt 'delete [] S_private'. –

+0

Auch ich bekomme das Fällen von Vektor Sie nicht ein dynamisches Array (Std :: Vector), sondern eine mathematische Vektor. Sie haben [vector] (http://stackoverflow.com/questions/tagged/vector) für dynamische Arrays eingegeben. Ist das wirklich was du willst? Deine Frage ist mir nicht klar. –

Antwort

7

Sie haben ein wenig zu graben es jetzt online zu finden, aber in Abschnitt 2.15 des OpenMP Standard, wo Benutzer deklarierte Reduzierungen diskutiert werden, werden Sie feststellen, dass "Der spezielle Bezeichner omp_orig kann auch in der Initialisierer-Klausel erscheinen und bezieht sich auf den Speicher der ursprünglichen zu reduzierenden Variable."

So können Sie initializer (omp_priv=TCmplxVec(omp_orig.size(),0)) oder nur initalizer (omp_priv(omp_orig)) verwenden, um den Vektor in der Reduktion zu initialisieren.

So funktioniert das (beachten Sie, dass Sie keine eigene Routine schreiben müssen; Sie können std :: transform und std :: plus verwenden, um Ihre Vektoren hinzuzufügen; Sie könnten auch std :: valarray anstelle von Vektoren verwenden je nachdem, wie Sie sie verwenden, der Operator + hat bereits definiert):

#include <complex> 
#include <vector> 
#include <algorithm> 
#include <functional> 
#include <iostream> 
#include <omp.h> 

typedef std::vector< std::complex<float> > TCmplxVec; 

#pragma omp declare reduction(+ : TCmplxVec : \ 
     std::transform(omp_in.begin(), omp_in.end(), \ 
         omp_out.begin(), omp_out.begin(), \ 
         std::plus< std::complex<float> >())) \ 
         initializer (omp_priv(omp_orig)) 

int main(int argc, char *argv[]) { 

    int size; 

    if (argc < 2) 
     size = 10; 
    else 
     size = atoi(argv[1]); 

    TCmplxVec result(size,0); 

    #pragma omp parallel reduction(+ : result) 
    { 
     int tid=omp_get_thread_num(); 

     for (int i=0; i<std::min(tid+1,size); i++) 
      result[i] += tid; 
    } 

    for (int i=0; i<size; i++) 
     std::cout << i << "\t" << result[i] << std::endl; 

    return 0; 
} 

Ausführen dieses

$ OMP_NUM_THREADS=1 ./reduction 8 
0 (0,0) 
1 (0,0) 
2 (0,0) 
3 (0,0) 
4 (0,0) 
5 (0,0) 
6 (0,0) 
7 (0,0) 

$ OMP_NUM_THREADS=4 ./reduction 8 
0 (6,0) 
1 (6,0) 
2 (5,0) 
3 (3,0) 
4 (0,0) 
5 (0,0) 
6 (0,0) 
7 (0,0) 

$ OMP_NUM_THREADS=8 ./reduction 8 
0 (28,0) 
1 (28,0) 
2 (27,0) 
3 (25,0) 
4 (22,0) 
5 (18,0) 
6 (13,0) 
7 (7,0) 
+0

Danke für die tolle Antwort und die Referenzverbindung zum OpenMP-Standard! –

Verwandte Themen