首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么编译器会忽略OpenMP编译指示?

为什么编译器会忽略OpenMP编译指示?
EN

Stack Overflow用户
提问于 2011-01-25 20:17:14
回答 4查看 9.3K关注 0票数 1

在下面的C代码中,我在一个嵌套循环中使用了OpenMP。因为出现了竞态条件,所以我想在最后执行原子操作:

代码语言:javascript
复制
double mysumallatomic() {

  double S2 = 0.;
  #pragma omp parallel for shared(S2)
  for(int a=0; a<128; a++){
    for(int b=0; b<128;b++){
      double myterm = (double)a*b;
      #pragma omp atomic
      S2 += myterm;
    }
  }
  return S2;
}

问题是,#pragma omp atomic对程序行为没有任何影响,即使我删除它,也不会发生任何事情。即使我将其更改为#pragma oh_my_god,我也不会得到任何错误!

我想知道这里出了什么问题,我是否可以告诉编译器在检查omp编译指示时更加严格,或者为什么我在进行最后一次更改时没有得到错误

PS:对于编译,我使用:

代码语言:javascript
复制
gcc-4.2 -fopenmp main.c functions.c -o main_elec_gcc.exe

PS2:新的代码给了我同样的问题,并基于吉莱斯皮的想法:

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <omp.h>
#include <math.h>

#define NRACK 64
#define NSTARS 1024

double mysumallatomic_serial(float rocks[NRACK][3], float moon[NSTARS][3],
                             float qr[NRACK],float ql[NSTARS]) {
  int j,i;
  float temp_div=0.,temp_sqrt=0.;
  float difx,dify,difz;
  float mod2x, mod2y, mod2z;
  double S2 = 0.;

  for(j=0; j<NRACK; j++){
    for(i=0; i<NSTARS;i++){     
      difx=rocks[j][0]-moon[i][0];
      dify=rocks[j][1]-moon[i][1];
      difz=rocks[j][2]-moon[i][2];
      mod2x=difx*difx;
      mod2y=dify*dify;
      mod2z=difz*difz;
      temp_sqrt=sqrt(mod2x+mod2y+mod2z);
      temp_div=1/temp_sqrt;
      S2 += ql[i]*temp_div*qr[j];       
    }
  }
  return S2;
}

double mysumallatomic(float rocks[NRACK][3], float moon[NSTARS][3], 
                      float qr[NRACK],float ql[NSTARS]) {
  float temp_div=0.,temp_sqrt=0.;
  float difx,dify,difz;
  float mod2x, mod2y, mod2z;
  double S2 = 0.;

  #pragma omp parallel for shared(S2)
  for(int j=0; j<NRACK; j++){
    for(int i=0; i<NSTARS;i++){
      difx=rocks[j][0]-moon[i][0];
      dify=rocks[j][1]-moon[i][1];
      difz=rocks[j][2]-moon[i][2];
      mod2x=difx*difx;
      mod2y=dify*dify;
      mod2z=difz*difz;
      temp_sqrt=sqrt(mod2x+mod2y+mod2z);
      temp_div=1/temp_sqrt;
      float myterm=ql[i]*temp_div*qr[j];    
      #pragma omp atomic
      S2 += myterm;
    }
  }
  return S2;
}
int main(int argc, char *argv[]) {
  float rocks[NRACK][3], moon[NSTARS][3];
  float qr[NRACK], ql[NSTARS];
  int i,j;

  for(j=0;j<NRACK;j++){
    rocks[j][0]=j;
    rocks[j][1]=j+1;
    rocks[j][2]=j+2;
    qr[j] = j*1e-4+1e-3;
    //qr[j] = 1;
  }

  for(i=0;i<NSTARS;i++){
    moon[i][0]=12000+i;
    moon[i][1]=12000+i+1;
    moon[i][2]=12000+i+2;
    ql[i] = i*1e-3 +1e-2 ;
    //ql[i] = 1 ;
  }
  printf(" serial: %f\n", mysumallatomic_serial(rocks,moon,qr,ql));
  printf(" openmp: %f\n", mysumallatomic(rocks,moon,qr,ql));
  return(0);
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-01-25 21:25:33

  1. 使用标志-Wall突出显示杂注错误。例如,当我拼写atomic错误时,我会得到以下警告。

main.c:15: warning: ignoring #pragma omp atomic1

  • I'm你当然知道,但以防万一,你的例子应该用你使用omp并行的reduction

  • When来处理,默认情况下所有变量都是共享的。这不是你想要的情况。例如,每个线程将有一个不同的值difx。相反,您的循环应该是:

(j=0;j

票数 3
EN

Stack Overflow用户

发布于 2017-01-05 12:26:07

我知道这是一个老帖子,但我认为问题在于gcc参数的顺序,-fopenmp应该在编译行的末尾。

票数 1
EN

Stack Overflow用户

发布于 2011-01-25 21:38:00

首先,根据实现的不同,缩减可能比使用原子更好。我会同时尝试这两种方法,并对它们进行计时,以确定它们是否正确。

其次,如果你忽略了原子,你可能会也可能看不到与比赛相关的问题(错误的结果)。这一切都与时间有关,从一次跑到下一次可能会有很大的不同。我见过在150,000次运行中只有一次结果错误的情况,而其他情况下结果一直都是错误的。

第三,语用背后的想法是,如果它们没有效果,用户不需要知道它们。除此之外,Unix (及其衍生产品)的哲学是,除非有问题,否则它是安静的。也就是说,许多实现都有某种标志,这样用户就可以获得更多信息,因为他们不知道发生了什么。您可以使用gcc尝试-Wall,至少它应该将oh_my_god杂注标记为被忽略。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4793363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档