OpenMP: OpenMP同步构造

来源:互联网 发布:mysql exists 编辑:程序博客网 时间:2024/05/17 08:19

同步构造:Synchronization Constructs

(1)什么是同步构造?

         OpenMP用于并行编程,自然,就会有“数据竞争”等相关问题。所以,OpenMP也提供了一些同步构造的指令,用于进行同步(synchronization)。

(2)同步构造之master指令

        指令功能:master指令指定一个区域只会被一个team中的主线程(master thread)执行,team内的其他线程都会忽略此区域。此指令没有隐含的等待。

指令格式:

#pragma omp master  newline     structured_block
指令限制:master指令不允许跳出或跳进(goto等)master块。

(3)同步构造之critical指令

指令功能:critical指令指定某一区域的代码每次只能同时被一个线程执行。

指令格式:

#pragma omp critical [ (name) ]  newline     structured_block

指令限制:critical指令不允许跳出或跳进(goto等)critical块。

说明:

         如果一个执行正在执行critical块的代码,并且其他线程也达到了critical块,那么这个线程会阻塞等待,直到第一个线程执行完critical的代码。其实,critical就相当于简化的win32多线程中的临界区或锁的概念。

实例:

#include <stdio.h>  int g;  #define ADD_COUNT   100000    int main(int argc, char *argv[])  {      printf("Masterthread started\n\n");    #pragma omp parallel      {          for (int i = 0; i < ADD_COUNT;i ++)          {  #pragma omp critical              g = g + 1;      // Will cause data races without critical directive.          }      }// End of parallel region        printf("g = %d\n", g);      printf("Expected g = %d\n",ADD_COUNT * 4);        // Assume the thread number is 4.        printf("Masterthread finished\n");        return(0);  }  

         这里,如果不使用critical,得到的结果将会不正确,就是由于数据竞争引起的。

         下面的例子是同样的数据竞争的例子,这两个例子比较一下也可以加深对parallel和parallel for的区别。

#include <stdio.h>  int g;  #define ADD_COUNT   1000000    int main(int argc, char *argv[])  {      printf("Masterthread started\n\n");    #pragma omp parallel for          for (int i = 0; i < ADD_COUNT;i ++)          {  #pragma omp critical              g = g + 1;      // Will cause data races without critical directive.          } // End of parallel for region        printf("g = %d\n",g);      printf("Expected g = %d\n", ADD_COUNT);        printf("Masterthread finished\n");        return(0);  }  

       关于name选项:在critical中,还有一个name的参数,critical可以指定代码段的name,同一个name的代码段被当成同一个代码段,所有未命名的代码段都当作一个代码段。

下面的两个例子对比来理解name的作用:

#include <stdio.h>  int g;  int g1;  #define ADD_COUNT   1000000    int main(int argc, char *argv[])  {      printf("Masterthread started\n\n");    #pragma omp parallel for          for (int i = 0; i < ADD_COUNT;i ++)          {  #pragma omp critical (namex)              g = g + 1;          // Will cause data races without critical directive.    #pragma omp critical (namey)              g1 = g1 + 1;        // Will cause data races without critical directive.          } // End of parallel for region        printf("g = %d, g1 = %d\n",g, g1);      printf("Expected g = g1 = %d\n", ADD_COUNT);        printf("Masterthread finished\n");        return(0);  }  

       这个例子定义了两个全局变量g和g1,分别运算,所以可以使用两个critical进行同步,那么第一个线程在操作namex段的代码(g)的时候,另一个线程(第二个线程)可能在等待,然后,第一个线程进入namey代码段,那么此时第二个线程就可以执行namex段的代码了,由于分别是g和g1的操作,这样是完全允许同时进行的。然而,下面的例子,使用不同的命名的critical,就会导致结果错误:

#include <stdio.h>  int g;  int g1;  #define ADD_COUNT   1000000    int main(int argc, char *argv[])  {      printf("Masterthread started\n\n");    #pragma omp parallel for      for (int i = 0; i < ADD_COUNT;i ++)      {  #pragma omp critical (namex)          g = g + 1;    #pragma omp critical (namey)          g = g + 1;          // Still data races!              } // End of parallel for region        g1 = g;      printf("g = %d, g1 = %d\n",g, g1);      printf("Expected g = g1 = %d\n",ADD_COUNT);        printf("Masterthread finished\n");        return(0);  } 

(4)同步构造之barrier指令

        指定作用:barrier是最简单的同步指令了,用于同步team中的所有线程。当一个线程达到了barrier后,它会在此处等待知道其它所有线程都执行到此处。

指令格式:

#pragma omp barrier  newline  

(5)同步构造之taskwait指令

OpenMP3.0新增加的指令,和task构造指令相关。

(6)同步构造之atomic指令

        指令作用:指定某一内存位置必须原子操作的形式更新。相当于简化的critical的使用。

指令格式:

#pragma omp atomic  newline     statement_expression  

说明:atomic后面不是一个structed bock,而是一个表达式。atomic的使用有一些格式要求,具体参考OpenMP spec说明。

(7)同步构造之flush指令

       指令作用:指定一个同步点,在此处,线程变量会写入到真实的内存中去。

指令格式:

#pragma omp flush (list)  newline  

(8)同步构造之ordered指令

       指定for循环迭代和串行一样的顺序执行。

       只能用于指令了ordered子句的for指令。

指令格式:

#pragma omp for ordered [clauses...]     (loop region)  #pragma omp ordered  newline     structured_block     (endo of loop region)  

说明:

        对于基本的使用,master,critical,barrier指令需要掌握和理解,其他指令,在以后逐步理解。

OpenMP Tutorial(Synchronization Constructs):https://computing.llnl.gov/tutorials/openMP/#Synchronization