2015-04-14 11 views
5

Sto cercando di definire la mia riduzione per i vettori del complesso <float>, seguendo this answer alla domanda Reducing on array in OpenMP.Riduzione definita dall'utente su vettori di dimensioni variabili

Ma la dimensione dei miei vettori non è fissa al momento della compilazione, quindi non sono sicuro di come definire l'inizializzatore per il vettore nel pragma declare reduction. Cioè, non posso semplicemente avere

initializer(omp_priv=TComplexVector(10,0)) 

Ma l'inizializzatore è necessario per i vettori.

Come posso passare alla clausola di inizializzazione la dimensione del vettore di cui ho bisogno in fase di esecuzione? Quello che ho finora è inferiore:

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

vostre domande suona come potrei essere interessante, ma io davvero non so cosa sei chiedendo. Hai bisogno di più codice less less e il codice deve essere generale e non dovrebbe contenere dettagli di cui probabilmente sei a conoscenza. –

+0

Per dargli la tua lunghezza invece di 'int S_private [10] = {0};' fai 'int * S_private = new int [n]()' e poi dopo la sezione critica fai 'delete [] S_private'. –

+0

Anche io ottengo l'abbattimento per vettore non intendi un array dinamico (std :: vector) ma un vettore matematico. Hai taged [vector] (http://stackoverflow.com/questions/tagged/vector) che è per gli array dinamici. E 'davvero ciò che vuoi? La tua domanda non mi è chiara. –

risposta

7

Devi scavare un po 'per trovare on-line in questo momento, ma nella sezione 2.15 del OpenMP Standard, in cui vengono discusse le riduzioni dall'utente dichiarato, troverete che "L'identificatore speciale omp_orig può anche apparire nella clausola di inizializzazione e farà riferimento alla memorizzazione della variabile originale da ridurre."

Quindi è possibile utilizzare initializer (omp_priv=TCmplxVec(omp_orig.size(),0)) o solo initalizer (omp_priv(omp_orig)) per inizializzare il vettore nella riduzione.

Quindi i seguenti lavori (si noti che non è necessario scrivere la propria routine, è possibile utilizzare std :: transform e std :: plus per aggiungere i vettori, si potrebbe anche usare std :: valarray piuttosto che i vettori , a seconda di come li usate, che ha operatore + già definito):

#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; 
} 

l'esecuzione di questo dà

$ 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

grazie per l'ottima risposta e il link di riferimento allo standard OpenMP! –