格式:
Fortran |
!$OMP CRITICAL [ name ]
block
!$OMP END CRITICAL |
C/C++ |
#pragma omp critical [ name ] newline
structured_block |
目的:
注意:
限制:
例子:
/*在临界区寻找正整数数组的最大元素*/
int main()
{
int max=0;
int a[10]={11,2,33,49,113,20,321,250,689,16};
#pragma omp parallel for
for(int j=0;j<10;j++)
{
int temp=a[j];
printf("temp=a[%d]=%d,id=%d\n",j,a[j],omp_get_thread_num());
#pragma omp critical
{
if(temp>max)
max=temp;
printf("temp=%d,max=%d,id=%d\n",temp,max,omp_get_thread_num());
}
}
printf("max=%d\n",max);
return 0;
}
gcc -fopenmp -std=c99 -o critical critical.c (-fopenmp编译并行结构、-std=c99是因为for内定义了变量初始类型int j=0)
./critical
输出:
temp=a[1]=2,id=1
temp=2,max=2,id=1
temp=a[3]=49,id=3
temp=49,max=49,id=3
temp=a[6]=321,id=6
temp=321,max=321,id=6
temp=a[5]=20,id=5
temp=20,max=321,id=5
temp=a[9]=16,id=9
temp=16,max=321,id=9
temp=a[2]=33,id=2
temp=33,max=321,id=2
temp=a[4]=113,id=4
temp=113,max=321,id=4
temp=a[8]=689,id=8
temp=689,max=689,id=8
temp=a[7]=250,id=7
temp=250,max=689,id=7
temp=a[0]=11,id=0
temp=11,max=689,id=0
max=689
或者
temp=a[0]=11,id=0
temp=a[4]=113,id=4
temp=a[9]=16,id=9
temp=a[5]=20,id=5
temp=a[6]=321,id=6
temp=a[3]=49,id=3
temp=a[1]=2,id=1
temp=a[8]=689,id=8
temp=a[7]=250,id=7
temp=a[2]=33,id=2
temp=11,max=11,id=0
temp=250,max=250,id=7
temp=2,max=250,id=1
temp=113,max=250,id=4
temp=49,max=250,id=3
temp=20,max=250,id=5
temp=16,max=250,id=9
temp=689,max=689,id=8
temp=321,max=689,id=6
temp=33,max=689,id=2
max=689
输出结果表明,第一个printf处是并行运行的,第二个printf位于critical临界区内,critical指定某一区域的代码,每次只能同时被一个线程执行。
#pragma omp critical [(name)]
{
<临界区代码>
}
critical的语义是指在任意时刻只有一个(或是最多一个)线程在执行临界区内的代码, 其目的是对于临界区内的线程之间共享的资源进行保护,比如几个线程对一个公共链表进行插入或删除操作,此时就需要使用critical, 否者该链表中的数据可能不一致。在OpenMP中,临界区的名字是可选的,所有的临界区都是外部链接的,也就是说是他们是公共变量,是所有线程可见的,不管该线程属于哪个组。对于没有指定名字的临界区,OpenMP编译时认为所有的没有指定名字的临界区,都对应一个外部(或全局)的临界区。不同于一些常见的OpenMP结构语句,临界区结构的末尾并没有一个隐含的同步路障。临界区的代码应该是一个块结构(structured block), 其中不允许有返回(return), 退出(exit), 或者从里面跳出(go to)语句。