idea di base
Ciò può essere realizzato senza alcuna critical
o atomic
sezioni parellelization-rottura creando un custom reduction. Fondamentalmente, definisci un oggetto che memorizza sia l'indice che il valore, quindi crea una funzione che ordina due di questi oggetti solo dal valore, non dall'indice.
dettagli
Un oggetto per memorizzare un indice e valore di insieme:
typedef std::pair<unsigned int, float> IndexValuePair;
È possibile accedere all'indice accedendo alla proprietà first
e il valore accedendo alla proprietà second
, vale a dire,
IndexValuePair obj(0, 2.345);
unsigned int ix = obj.first; // 0
float val = obj.second; // 2.345
Definire una funzione per ordinare due IndexValuePair
oggetti:
IndexValuePair myMin(IndexValuePair a, IndexValuePair b){
return a.second < b.second ? a : b;
}
Poi, costruire una riduzione personalizzato seguendo le linee guida della OpenMP documentation:
#pragma omp declare reduction \
(minPair:IndexValuePair:omp_out=myMin(omp_out, omp_in)) \
initializer(omp_priv = IndexValuePair(0, 1000))
In questo caso, ho scelto per inizializzare l'indice a 0 e il valore a 1000 Il valore deve essere inizializzato su un numero maggiore del valore massimo che si prevede di ordinare.
funzionale Esempio
Infine, combinare tutti questi pezzi con il parallelo per ciclo!
// Compile with g++ -std=c++11 -fopenmp demo.cpp
#include <iostream>
#include <utility>
#include <vector>
typedef std::pair<unsigned int, float> IndexValuePair;
IndexValuePair myMin(IndexValuePair a, IndexValuePair b){
return a.second < b.second ? a : b;
}
int main(){
std::vector<float> vals {10, 4, 6, 2, 8, 0, -1, 2, 3, 4, 4, 8};
unsigned int i;
IndexValuePair minValueIndex(0, 1000);
#pragma omp declare reduction \
(minPair:IndexValuePair:omp_out=myMin(omp_out, omp_in)) \
initializer(omp_priv = IndexValuePair(0, 1000))
#pragma omp parallel for reduction(minPair:minValueIndex)
for(i = 0; i < vals.size(); i++){
if(vals[i] < minValueIndex.second){
minValueIndex.first = i;
minValueIndex.second = vals[i];
}
}
std::cout << "minimum value = " << minValueIndex.second << std::endl; // Should be -1
std::cout << "index = " << minValueIndex.first << std::endl; // Should be 6
return EXIT_SUCCESS;
}
non è male per condividere variabili (QuestoValore, min) tra le discussioni senza un mutex? –
Sembra che questa riduzione abbia fatto molte cose, quindi non sono così chiaro se è condiviso o meno. Ho provato una versione senza riduzione, i thread funzionano liberamente, la parte assegnata è critica e la velocità di esecuzione si riduce effettivamente. – xxbidiao