Ich habe einen Code, der viele Iterationen ausführt und nur wenn eine Bedingung erfüllt ist, wird das Ergebnis der Iteration gespeichert. Dies wird natürlich als while-Schleife ausgedrückt. Ich versuche, den Code parallel laufen zu lassen, da jede Realisierung unabhängig ist. Also ich habe dies:OpenMP While-Schleife
while(nit<avit){
#pragma omp parallel shared(nit,avit)
{
//do some stuff
if(condition){
#pragma omp critical
{
nit++;
\\save results
}
}
}//implicit barrier here
}
und das funktioniert gut ... aber es gibt eine Barriere nach jeder Erkenntnis, was bedeutet, dass, wenn das, was ich in dem parallelen Block täte dauert länger in einer Iteration als die andere, Alle meine Threads warten darauf, dass sie beendet wird, anstatt mit der nächsten Iteration fortzufahren.
Gibt es eine Möglichkeit, diese Barriere zu vermeiden, damit die Gewinde weiter funktionieren? Ich bin im Durchschnitt Tausende von Iterationen, so ein paar mehr nicht weh tun (wenn die nit
Variable in bereits laufenden Threads nicht erhöht wurde) ...
Ich habe versucht, dies in eine Parallele für, aber die Durch die automatische Erhöhung der for-Schleife wird die Variable nit
deaktiviert. Dies ist mein Versuch:
#pragma omp parallel shared(nit,avit)
{
#pragma omp for
for(nit=0;nit<avit;nit++){
//do some stuff
if(condition){
\\save results
} else {
#pragma omp critical
{
nit--;
}
}
}
}
und es hält zu arbeiten und um die for-Schleife gehen, wie erwartet, aber meine nit
Variable nimmt unvorhersehbare Werte ... wie man es von der Zunahme und Abnahme der es durch verschiedene Threads erwarten könnte zu anderen Zeiten.
Ich habe auch versucht, den Zuwachs in der Lassen Schleife leer, aber es funktioniert nicht kompilieren, oder versuchen, meinen Code zu verleiten keinen Zuwachs in der for-Schleife zu haben, wie
...
incr=0;
for(nit=0;nit<avit;nit+=incr)
...
aber dann meine Code stürzt ab ...
Irgendwelche Ideen?
Dank
Edit: Hier ist ein Arbeits minimal Beispiel für den Code auf einer while-Schleife:
#include <random>
#include <vector>
#include <iostream>
#include <time.h>
#include <omp.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int main(){
int nit,dit,avit=100,t,j,tmax=100,jmax=10;
vector<double> Res(10),avRes(10);
nit=0; dit=0;
while(nit<avit){
#pragma omp parallel shared(tmax,nit,jmax,avRes,avit,dit) private(t,j) firstprivate(Res)
{
srand(int(time(NULL))^omp_get_thread_num());
t=0; j=0;
while(t<tmax&&j<jmax){
Res[j]=rand() % 10;
t+=Res[j];
if(omp_get_thread_num()==5){
usleep(100000);
}
j++;
}
if(t<tmax){
#pragma omp critical
{
nit++;
for(j=0;j<jmax;j++){
avRes[j]+=Res[j];
}
for(j=0;j<jmax;j++){
cout<<avRes[j]/nit<<"\t";
}
cout<<" \t nit="<<nit<<"\t thread: "<<omp_get_thread_num();
cout<<endl;
}
} else{
#pragma omp critical
{
dit++;
cout<<"Discarded: "<<dit<<"\r"<<flush;
}
}
}
}
return 0;
}
Ich fügte den usleep
Teil einen Thread zu simulieren, die länger als die andere. Wenn Sie das Programm ausführen, müssen alle Threads darauf warten, dass Thread 5 beendet wird, und dann starten sie den nächsten Lauf. was ich versuche zu tun, ist genau solche Wartezeiten zu vermeiden, d. h. ich möchte, dass die anderen Threads die nächste Iteration auswählen, ohne zu warten, bis die 5 fertig ist.
Es ist nicht wirklich möglich, die Frage ohne ein genaueres Verständnis von * einigen Sachen * richtig zu beantworten. Vor allem haben wir keine Ahnung, ob 'nit' in * some stuff * aufgerufen wird und was passieren soll, wenn mehrere Threads 'condition' zur gleichen Zeit haben, oder 'nit' wurde mehrmals aktualisiert, während ein Thread * einige Sachen gemacht hat * ... Es ist schwer, aber für eine gute, spezifische Antwort müssen Sie ein [mcve] erstellen. – Zulan
Danke für den Kommentar @Zulan. Ich habe die Frage bearbeitet, um am Ende ein minimales Arbeitsbeispiel hinzuzufügen. Hoffe das klärt die Dinge. –