使用OpenMP实现嵌套循环内的计数器 [英] Counter inside nested loops with OpenMP

查看:0
本文介绍了使用OpenMP实现嵌套循环内的计数器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的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 	 xMax*yMax = %d
", 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) 	 where xMax*yMax = %d
", 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) 	 where xMax*yMax = %d
", i, (double)i/all,  all);
    return 0;
}

现在:

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

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

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

推荐答案

问题在于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++;
}

这篇关于使用OpenMP实现嵌套循环内的计数器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆