我有一个运行多次迭代的代码,只有满足条件时,才会保存迭代的结果。这自然地表示为 while 循环。我试图使代码并行运行,因为每个实现都是独立的。所以我有这个:
while(nit<avit){
#pragma omp parallel shared(nit,avit)
{
//do some stuff
if(condition){
#pragma omp critical
{
nit++;
\\save results
}
}
}//implicit barrier here
}
这工作正常...但是每次实现之后都会存在一个障碍,这意味着如果我在并行块内所做的事情在一次迭代中比其他迭代花费的时间更长,那么我的所有线程都在等待它完成,而不是继续下一次迭代。
有没有办法避免这种障碍,使线程继续工作?我平均进行了数千次迭代,所以多进行几次也没有什么坏处(以防万一nit
变量在已经运行的线程中尚未增加)...
我试图将其变成并行的 for,但是 for 循环中的自动增量使得nit
变量变得疯狂。这是我的尝试:
#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--;
}
}
}
}
正如预期的那样,它继续工作并围绕 for 循环进行,但是我的nit
变量采用不可预测的值...正如人们可以从不同线程在不同时间增加和减少它所期望的那样。
我也尝试将 for 循环中的增量留空,但它无法编译,或者试图欺骗我的代码,使其在 for 循环中没有增量,例如
...
incr=0;
for(nit=0;nit<avit;nit+=incr)
...
但后来我的代码崩溃了......
有任何想法吗?
Thanks
编辑:这是 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;
}
我添加了usleep
部分来模拟一个线程比其他线程花费更长的时间。如果运行该程序,所有线程都必须等待线程 5 完成,然后才能开始下一次运行。我想要做的正是避免这种等待,即我希望其他线程选择下一个迭代而不等待 5 完成。