OpenMP while loop
Tengo un código que ejecuta muchas iteraciones y solo si se cumple una condición, se guarda el resultado de la iteración. Esto se expresa naturalmente como un ciclo while. Estoy intentando hacer que el código se ejecute en paralelo, ya que cada realización es independiente. Entonces tengo esto:
while(nit<avit){
#pragma omp parallel shared(nit,avit)
{
//do some stuff
if(condition){
#pragma omp critical
{
nit++;
\\save results
}
}
}//implicit barrier here
}
y esto funciona bien ... pero hay una barrera después de cada realización, lo que significa que si las cosas que estoy haciendo dentro del bloque paralelo tardan más en una iteración que las otras, todos mis hilos están esperando que termine, en lugar de continuando con la próxima iteración.
¿Hay alguna manera de evitar esta barrera para que los hilos sigan funcionando? Estoy promediando miles de iteraciones, por lo que algunas más no duelen (en caso de que elnit
la variable no se ha incrementado en subprocesos que ya se están ejecutando) ...
He intentado convertir esto en un paralelo para, pero el incremento automático en el bucle for hace que elnit
la variable se vuelve loca. Este es mi intento:
#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--;
}
}
}
}
y sigue funcionando y dando vueltas por el ciclo for, como se esperaba, pero minit
La variable toma valores impredecibles ... como cabría esperar del aumento y la disminución de la misma por diferentes subprocesos en diferentes momentos.
También he intentado dejar el incremento en el bucle for en blanco, pero no se compila, o tratar de engañar a mi código para que no tenga un incremento en el bucle for, como
...
incr=0;
for(nit=0;nit<avit;nit+=incr)
...
pero luego mi código falla ...
¿Algunas ideas?
Gracias
Editar: Aquí hay un ejemplo mínimo de trabajo del código en un ciclo while:
#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;
}
Agregué elusleep
parte para simular un hilo que lleva más tiempo que los otros. Si ejecuta el programa, todos los subprocesos deben esperar a que finalice el subproceso 5, y luego comienzan la próxima ejecución. lo que intento hacer es precisamente evitar esa espera, es decir, me gustaría que los otros hilos elijan la próxima iteración sin esperar a que finalice 5.