openmp开始使用openmp


备注

OpenMP(Open MultiProcessing)是一种基于编译器指令的并行编程模型,它允许应用程序开发人员逐步向其应用程序代码添加并行性。

用于并行编程的OpenMP API规范提供了一个应用程序编程接口(API),在大多数平台上支持C,C ++和Fortran中的多平台共享内存多处理编程。它由一组影响运行时行为的编译器指令,库例程和环境变量组成。

由于OpenMP侧重于节点内的并行性(共享内存多处理),因此可以与消息传递编程模型(如MPI)结合使用,以在多个节点上执行。

版本

语言发布日期
4.5 C / C ++ / Fortran的 2015年11月1日
4 C / C ++ / Fortran的 2013-07-01
3.1 C / C ++ / Fortran的 2011-07-01
3.0 C / C ++ / Fortran的 2008-05-01
2.5 C / C ++ / Fortran的 2005-05-01
2.0C C / C ++ 2002-03-01
2.0F Fortran语言 2000-11-01
1.0C C / C ++ 1998-10-01
1.0F Fortran语言 1997-10-01

汇编

有许多编译器支持不同版本的OpenMP规范。 OpenMP 在此处使用支持它的编译器和支持的版本维护一个列表。通常,要编译(和链接)具有OpenMP支持的应用程序,您只需要添加编译标志,如果使用OpenMP API,则需要包含OpenMP标头(omp.h)。虽然头文件具有固定名称,但编译标志取决于编译器。以下是编译器的非详尽列表和启用OpenMP的标志。

  • GCC(包括gcc,g ++和gfortran): - -fopenmp
  • LLVM:-fopenmp
  • 英特尔编译器套件(包括icc,icpc和ifort): - -qopenmp (和-fopenmp 用于与GCC / LLVM兼容)
  • IBM XL编译器套件(包括xlc,xlC和xlf): - -xlsmp=omp
  • PGI编译器套件(包括pgcc pgc ++ pgfortran):' - mp'

使用OpenMP并行hello world

#include <omp.h>
#include <stdio.h>

int main (int argc, char *argv[])
{
   #pragma omp parallel
   {
     printf ("Hello world! I'm thread %d out of %d threads.\n",
             omp_get_thread_num(), omp_get_num_threads());
   }
   return 0;
}
 

这段代码只是创建了一个线程组(根据环境变量OMP_NUM_THREADS - 如果没有定义,将在系统上为每个逻辑核心创建一个),并且每个线程除了打印典型的Hello world消息之外还将标识自己。

减少例子

#include <omp.h>
void main ()
{     
    int i;       
    double ZZ, func(), res=0.0;

    #pragma omp parallel for reduction(+:res) private(ZZ) 
    for (i=0; i< 1000; i++){
        ZZ = func(I);
        res = res + ZZ; 
    }
}
 

在最后一行:实际上添加到私有副本,然后在循环后组合。编译器负责细节。

工作共享构造 - For循环的示例

double  res[MAX];  int i;
#pragma omp parallel 
{    
    #pragma omp for
    for (i=0;i< MAX; i++) {
        res[i] = huge();
    } 
}    
 

for循环将并行执行。 huge()是一种可能需要很长时间才能执行的方法。 OpenMP支持将上述代码编写为的快捷方式:

double  res[MAX];  int i;
#pragma omp parallel for
for (i=0;i< MAX; i++) {
    res[i] = huge();
} 
 

我们还可以有一个schedule子句,它影响循环迭代如何映射到线程。例如:

#pragma omp parallel
#pragma omp for schedule(static)
for(i=0;I<N;i++) {
    a[i] = a[i] + b[i];
}
 

不同风格的调度是:

schedule(静态[,chunk])
每个线程处理大小“块”的迭代块。
如果未指定:尽可能均匀地分配给可用线程

时间表(动态[,块])
每个线程从队列中抓取“块”迭代,直到所有迭代都被处理完毕。

时间表(引导[,块])
线程动态地抓取迭代块。随着计算的进行,块的大小开始变大并缩小到“块”大小。

时间表时(runtime)
从OMP_SCHEDULE环境变量获取的计划和块大小。