OpenMP的for循环忽略num_threads子句

问题描述:

我在VS2008下面的代码:OpenMP的for循环忽略num_threads子句

int i,j; 
bool pr = false; 
#pragma omp parallel for private(pr) num_threads(2) 
for(i=0;i<PIC_X;i++) 
{ 
    int rank = omp_get_thread_num(); 
    int count = omp_get_num_threads(); 
    if (!pr) 
    { 
     printf_s("Hello from thread %d of %d\n", rank, count); 
     pr = true; 
    } 
    for(j=0;j<PIC_Y;j++) 
    { 
     // do stuff 
    } 
} 

(不试图使一个嵌套的OpenMP循环中,如果你想知道)。问题是,num_threads子句没有任何效果:我只输出了“来自线程0的Hello”。我也尝试使用omp_set_num_threads(2),无济于事。是什么赋予了?

+1

退房http://software.intel.com/en-us/articles/32-openmp-traps-for-c-developers/ - 它真的帮助我 – 2011-02-04 17:29:55

您已将pr设置在并行区域之外,然后通过将其置于私有子句中使其成为私有。这意味着每个线程都有一个pr,但私有pr变量不会被初始化。对pr使用firstprivate而不是private,以便私有变量被初始化。

但是,您对循环计数器默认情况下是不正确的。工作共享(或规范)(即变量i)的循环计数器是私有的(OMP V2.0规范的构造部分2.4.1节)。但是“j”不是。见的OpenMP V2.0规范(这是微软在VS2008支持),第2.7.2数据共享属性子句:

如果遇到一个平行或工作共享结构,当一个变量是可见的, 该变量未在共享属性子句或threadprivate 指令中指定,则该变量是共享的。在并行区域的动态 范围内声明的静态变量是共享的。堆分配内存(例如,使用C或C++中的 malloc()或C++中的新操作符)。 (但是,指向此 内存的指针可以是私有的,也可以是共享的。)具有在并行区域的动态范围内声明的自动存储器的持续时间的变量是私有的。

至于omp_get_num_threads()返回1,我能想到的是,你没有编译这个启用OpenMP标志。

如果OpenMP将外循环拆分为2(即一个进程获得0..PIC_X/2),而另一个获得后半部分,则只有一个进程会看到i == 0。

如果你的图像像我看到的所有图像一样组织起来,那么外层循环应该是Y,内层循环应该是X,内层循环应该是OpenMP的,因为这就是图像通常在内存中组织的方式。

+0

+1,即使OP编辑帖子以删除`if(i == 0)`code xcramps was original correct。 – 2011-02-04 16:45:47