Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading OpenMP while循环_Multithreading_C++11_For Loop_While Loop_Openmp - Fatal编程技术网

Multithreading OpenMP while循环

Multithreading OpenMP while循环,multithreading,c++11,for-loop,while-loop,openmp,Multithreading,C++11,For Loop,While Loop,Openmp,我有一个运行多次迭代的代码,只有当满足一个条件时,迭代的结果才会被保存。这自然表示为while循环。我试图使代码并行运行,因为每个实现都是独立的。所以我有这个: while(nit<avit){ #pragma omp parallel shared(nit,avit) { //do some stuff if(condition){ #pragma omp critical {

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

while(nit<avit){
    #pragma omp parallel shared(nit,avit)
    {
        //do some stuff
        if(condition){
            #pragma omp critical
            {
                nit++;
                \\save results
            }
        }
    }//implicit barrier here
}
正如预期的那样,它一直在for循环中运行,但是我的
nit
变量采用了不可预测的值。。。正如我们可以预期的,在不同的时间,不同的线程会增加和减少它

我还尝试将for循环中的增量留空,但它不会编译,或者尝试欺骗我的代码,使其在for循环中没有增量,如

...
incr=0;
for(nit=0;nit<avit;nit+=incr)
...
。。。
增量=0;

对于(nit=0;nit您基本上可以遵循与for相同的概念,但略有不同,以确保
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++;
     }
 }
int nit=0;
#pragma-omp并行
而(1){
国际本地单位;
#pragma omp原子读取
本地_nit=nit;
如果(本地\u nit>=avit){
打破
}
[...]
如果(…){
#pragma-omp-critical
{
#pragma-omp原子捕获
本地_nit=++nit;

对于(j=0;如果对某些东西没有更具体的理解,jIt实际上不可能正确地回答这个问题。特别是我们不知道是否在某些东西中访问了
nit
,以及当多个线程同时具有
条件时会发生什么,或者当ne thread正在做一些事情…这很难,但要得到一个好的、具体的答案,你必须创建一个。感谢@Zulan的评论。我编辑了这个问题,在最后添加了一个最小的工作示例。希望这能澄清问题。感谢@Zulan,稍作修改,这看起来(几乎)是做这个把戏!我不太熟悉
原子
,但它不允许我像
关键
那样添加一块代码…我需要所有线程都能够编写结果,并且它们的编写频率比只在最后更高…如果我这样做的话(j=0;j请记住,我现在明白了
atomic
只能用于单行指令。因此最后的代码必须有
关键的
部分用于编写。作为最后的更正,我相信
local\u nit=nit++;
应该是
nit++
,因为
local\u nit
在上面是更新的
#pragma omp atomic read local_nit=nit;
和阻止写入到结尾的
if
。再次感谢您的帮助。我的代码错误地使用了后缀而不是前缀increment。我修复了它和链接。使用正确的形式
local_nit=++nit;if(local_nit==avit)…
您可以在不使用昂贵的关键部分的情况下保护输出的写入。这更有意义…但这将再次只在程序结束时写入,对吗?我需要能够更频繁地检查结果,所以我想我确实需要一个关键部分…我可以“隐藏它”吗在一个
if
?:
#pragma omp原子捕获本地_wnit=++wnit;if(本地_wnit==wavit){#pragma omp critical{\\write;wnit-=local_wnit;}
其中
wnit
是一个全局写入计数器
local\u wnit
是一个本地处理的变量,
wavit
是一个共享变量,具有写入事件之间的迭代次数。这会有帮助吗?还是相同?感谢修复链接。如果您需要更新每个增量的结果(抱歉,我误读了您的问题),您也可以只使用一个关键部分进行更新。请参阅我编辑的答案。或者,如果只是总结关键部分的性能问题,或者如果
jmax
相当小,则可以进行缩减,以原子方式更新每个结果。最重要的是,您不想在关键部分读取计数器行动。
#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;
}
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++;
     }
 }