gpt4 book ai didi

multithreading - OpenMP while 循环

转载 作者:行者123 更新时间:2023-12-03 12:47:18 24 4
gpt4 key购买 nike

我有一个运行多次迭代的代码,只有在满足条件时,才会保存迭代的结果。这很自然地表示为一个while循环。我试图让代码并行运行,因为每个实现都是独立的。所以我有这个:

while(nit<avit){
#pragma omp parallel shared(nit,avit)
{
//do some stuff
if(condition){
#pragma omp critical
{
nit++;
\\save results
}
}
}//implicit barrier here
}

这工作正常......但每次实现后都有一个障碍,这意味着如果我在并行 block 内做的事情在一次迭代中比其他迭代花费更长的时间,我所有的线程都在等待它完成,而不是继续下一次迭代。

有没有办法避免这个障碍,让线程继续工作?我正在平均数千次迭代,所以再多一些不会受到伤害(如果 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)
...

但后来我的代码崩溃了......

有任何想法吗?

谢谢

编辑:这是 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 完成的情况下选择下一次迭代。

最佳答案

您基本上可以遵循与 this question 相同的概念。 , 略有不同以确保 avRes不是并行写入:

int nit = 0;
#pragma omp parallel
while(1) {
int local_nit;
#pragma omp atomic read
local_nit = nit;
if (local_nit >= avit) {
break;
}

[...]

if (...) {
#pragma omp critical
{
#pragma omp atomic capture
local_nit = ++nit;
for(j=0;j<jmax;j++){
avRes[j] += Res[j];
}
for(j=0;j<jmax;j++){
// technically you could also use `nit` directly since
// now `nit` is only modified within this critical section
cout<<avRes[j]/local_nit<<"\t";
}
}
} else {
#pragma omp atomic update
dit++;
}
}

它也适用于关键区域,但原子更有效。

您还需要考虑另一件事, rand()不应在并行上下文中使用。见 this question .对于 C++,使用来自 <random> 的私有(private)(即在并行区域内定义)随机数生成器.

关于multithreading - OpenMP while 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47349885/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com