使用OpenMP实现嵌套循环内的计数器 [英] Counter inside nested loops with OpenMP
本文介绍了使用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屋!
查看全文