【问题标题】:Counter inside nested loops with OpenMP使用 OpenMP 在嵌套循环内计数器
【发布时间】:2021-10-08 19:31:27
【问题描述】:

我在c program 中使用计数器来制作光栅图像以查看图像统计信息:每个盆地的相对大小(pixel counting)

我的程序很长,所以我做了Minimal, Reproducible Example。

第一个没有 OpenMP 的程序,它显示了我想要达到的目标(所有像素的数量):

#include <stdio.h>
#include <stdlib.h>


int main()
{

    int x;
    int xMax = 100;
    int y;
    int yMax = 100;
    
    
    
    int i= 0; 

    for (x = 0; x < xMax; x++) {

        for (y = 0; y < yMax; y++)
            {i++;}
        }

    printf("i = %d \t xMax*yMax = %d\n", i, xMax*yMax);
    return 0;
}

它正确计算像素(x,y):

 i = xMax*yMax

当我添加 OpenMP 时,这并不容易,但减少会有帮助

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>        // OpenMP


int i= 0; 

int main()
{

    int x;
    int xMax = 1000;
    int y;
    int yMax = 1000;
    int all = xMax*yMax;
    
    
    #pragma omp parallel for collapse(2) schedule(dynamic) reduction(+:i)
    for (x = 0; x < xMax; x++) {
        for (y = 0; y < yMax; y++)
            {i++;}
        }

    printf("i = %d = %f*(xMax*yMax) \t where xMax*yMax = %d\n", i, (double)i/all,  all);
    return 0;
}

当我将计数器隐藏在另一个函数中时,计数器没有正确更新


#include <stdio.h>
#include <stdlib.h>
#include <omp.h>        // OpenMP


int i= 0; 



void P(){

 i++;

}




int main()
{

    int x;
    int xMax = 1000;
    int y;
    int yMax = 1000;
    int all = xMax*yMax;
    
    
    
    

    #pragma omp parallel for collapse(2) schedule(dynamic) reduction(+:i)
    for (x = 0; x < xMax; x++) {

        for (y = 0; y < yMax; y++)
            {P();}
        }

    printf("i = %d = %f*(xMax*yMax) \t where xMax*yMax = %d\n", i, (double)i/all,  all);
    return 0;
}

现在:

gcc p.c -Wall -fopenmp
./a.out
i = 437534 = 0.437534*(xMax*yMax)    where xMax*yMax = 1000000

问题:计数器内部函数没有正确更新

问题:我应该如何更改才能正确更新计数器?

【问题讨论】:

    标签: c global-variables openmp nested-loops


    【解决方案1】:

    问题是reduction(+:i) 子句创建了一个局部变量i,你应该更改这个局部变量。但是,在您的代码中,您通过调用函数P 来增加全局变量,这不是线程安全的(增加它时会出现竞争条件)。所以,你只需要确保在调用函数P时增加本地i:

        void P(int& i){
           i++;
        }
    
        //in main:
        for (y = 0; y < yMax; y++)
                {P(i);}
    
    

    另一个(但速度较慢)选项是通过使用原子操作使函数P 线程安全。在这种情况下,您根本不需要减少:

    void P(){
    #pragma omp atomic
     i++;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      • 2016-07-27
      相关资源
      最近更新 更多