2013-03-11 13 views
5

intendo usare tamponi std::vector<size_t> buffer(100), uno per ogni filo in una parallelizzazione di un ciclo, come suggerito da questo codice:preassegnati std privato :: vector in OpenMP parallelized ciclo for C++

std::vector<size_t> buffer(100); 
#pragma omp parallel for private(buffer) 
for(size_t j = 0; j < 10000; ++j) { 
    // ... code using the buffer ... 
} 

Questo il codice non funziona. Sebbene sia presente un buffer per ogni thread, questi possono avere la dimensione 0.

Come posso allocare il buffer all'inizio di ogni thread? Posso ancora usare #pragma omp parallel for? E posso farlo più elegante di questo:

std::vector<size_t> buffer; 
#pragma omp parallel for private(buffer) 
for(size_t j = 0; j < 10000; ++j) { 
    if(buffer.size() != 100) { 
     #pragma omp critical 
     buffer.resize(100); 
    } 
    // ... code using the buffer ... 
} 
+0

Penso di vedere il problema ora. Il vettore non viene correttamente copiato nella regione OpenMP. Non sono sicuro di quello che dice lo standard OpenMP sulla costruzione di copia delle variabili 'private' nei thread. – Mysticial

+0

Se si desidera che siano separati, basta dichiarare il vettore all'interno della regione OpenMP. – Mysticial

+0

Grazie per il chiarimento.So come delcare il vettore all'interno della regione OpenMP se parallelizzo il loop manualmente. Ma funziona anche con '#pragma omp parallel for'? –

risposta

7

Spalato regione OpenMP, come mostrato in this question.

Quindi dichiarare il vettore all'interno della regione esterna, ma all'esterno del ciclo stesso. Questo renderà un vettore locale per ogni thread.

#pragma omp parallel 
{ 
    std::vector<size_t> buffer(100); 

#pragma omp for 
    for(size_t j = 0; j < 10000; ++j) { 
    { 

     // ... code using the buffer ... 

    } 
} 
7

La domanda e la risposta accettata sono stati intorno per un po ', ecco alcune informazioni che forniscono ulteriori indizi openMP e quindi potrebbe essere utile ad altri utenti.

In C++, gli oggetti private e firstprivate clausola di classe maniglia in modo diverso:

Dal v3.1 OpenMP Application Program Interface:

privato: il nuovo elemento della lista viene inizializzato, o ha un valore iniziale indefinito, come se fosse stato dichiarato localmente senza inizializzatore. L'ordine in cui sono chiamati i costruttori predefiniti per variabili private diverse del tipo di classe non è specificato.

firstprivate: per le variabili di tipo di classe, un costruttore di copia viene invocato per eseguire la inizializzazione delle variabili di lista.

cioè private chiama il costruttore di default, che firstprivate chiama il costruttore di copie della classe corrispondente.

Il costruttore di default di std::vector costruisce un contenitore vuoto senza elementi, questo è il motivo per cui i buffer hanno dimensioni 0.

Per rispondere alla domanda, questo sarebbe un altra soluzione senza necessità di suddividere la regione OpenMP:

std::vector<size_t> buffer(100, 0); 
#pragma omp parallel for firstprivate(buffer) 
for (size_t j = 0; j < 10000; ++j) { 
    // use the buffer 
} 

EDIT una parola di cautela riguardo variabili private in generale: la dimensione dello stack filettatura è limitato e se non esplicitamente impostato (variabile ambiente OMP_STACKSIZE) compilatore dipendente. Se si utilizzano variabili private con un ingombro di memoria di grandi dimensioni, l'overflow dello stack può diventare un problema.

+1

Grazie per questo. Questo è esattamente ciò che sospettavo riguardo agli oggetti e 'private' /' firstprivate'. Ma riguardo alla tua nota sulla dimensione dello stack, è completamente irrilevante dal momento che 'std :: vector' alloca la memoria sull'heap, e il contenitore' vector' effettivo deve solo memorizzare come 3 puntatori nello stack (nella maggior parte delle implementazioni). –

+0

Questa risposta è migliore perché riduce il numero di copie di 'buffer' da 10000 al numero di thread. – chrisdembia

+0

Posso fare qualcosa come dichiarare una matrice di vettori in primo piano, e quindi fare in modo che ogni thread acceda al vettore solo in uno "slot" di quell'array? L'ho fatto per variabili semplici come gli ints ma non mi sento sicuro che sia sicuro farlo con i vettori. –