#pragma omp critical-----OpenMP 参考 (同步构造)CRITICAL 指令

格式:

Fortran

 

!$OMP CRITICAL [ name ]

 

   block

 

!$OMP END CRITICAL

C/C++

 

#pragma omp critical [ name ]  newline

 

   structured_block



目的:

  • CRITICAL指令指定一块同一时间只能被一条线程执行的代码区域

注意:

  • 如果一条线程正在一个CRITICAL区域执行而另一个线程到达这个区域,并企图执行,那么它将会被阻塞,直到第一个线程离开这个区域.
  • 命名是可选项,使不同的CRITICAL区域共存:
  • 命名是全局标志符.具有相同命名的不同的CRITICAL区域被当作同一个区域
  • 所有未命名CRITICAL区域被当作同一个区域

限制:

  • 扩充CRITICAL 块是非法的.

例子:

/*在临界区寻找正整数数组的最大元素*/

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)语句。


你可能感兴趣的:(OpenMP)