OpenMP(一)概念及简单示例

243 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

OpenMP是一个面向共享存储的多CPU多线程并行编程接口。
共享存储是指所有CPU不需要网络连接而访问到同一块内存。所以OpenMP只局限于在单机之中进行并行。
目前混合并行编程都是通过OpenMP和MPI共同完成,其中MPI(消息传递接口)封装了socket,它能通过网络
连接在不同节点之间进行数据通信和共享。
OpenMP是fork-join模型
在我们使用OpenMP编写一个C程序时,有串行的程序块,也有并行的程序块。
进入main函数,主线程(master thread)会从上往下运行串行块,当碰到并行程序时,
它会fork出许多子线程去执行不同的任务,等到所有的子线程都完成时(这里有同步机制)再joinjoin之后是主线程在运行。再碰到并行块的时候会再fork
OpenMP的构成
  1. 编译指导语句
  2. 运行时库函数(Runtime Library)
  3. 环境变量

编译指导语句格式

#pragma omp <directive> [clause, ...]

注意它是以注释的方式出现的,如果正常gcc编译则会将其看成注释,得到的是一个串行程序,如果加上-fopenmp则会编译程并行程序

常用的directive
  • parallel:用在并行结构块之前,表示要并行
  • for:用在for循环之前,openmp会自动分配数据且并行化处理,它默认数据列表是私有的
  • sections:可并行执行的代码段各自用section标出
  • criticial :表示临界区
  • single :用在并行区域中,表示只被一个线程执行
  • flush : 刷新
  • barrier :栅栏,用来同步,碰到栅栏,所有程序都执行到barrier才能继续往下执行。
常用的clause
  • private:声明后面的变量是线程私有的
  • shared:声明后面的变量是所有线程共享的
  • default:设置默认下变量的共享属性,有shared和none,none是指不启用默认
  • firtstprivate:首先它是私有变量,但其初始值是主线程中同名变量的值
  • lastprivate:私有变量,将最后一个线程中变量的结果复制到主线程的同名变量中
  • reduction:指定哪些变量在并行处理结束后需要做规约(求向量所有元素的和就是典型 的规约操作)
  • copyin:指定一个threadprivate变量需要用主线程同名变量进行初始化
简单示例1

hello_omp.c

#include <omp.h>

#include <stdio.h>

  

int main(int argc, char *argv[]) {

  int nthreads, tid;

  /* Fork a team of threads giving them their own copies of variables */

  #pragma omp parallel private(nthreads, tid)

  {

    /* Obtain thread number */

    tid = omp_get_thread_num();

    nthreads = omp_get_num_threads();

    printf("Hello World from thread %d of %d\n", tid, nthreads);

  }

}

gcc编译

gcc -fopenmp hello_omp.c -o hello_omp

运行结果:

Hello World from thread 3 of 8
Hello World from thread 0 of 8
Hello World from thread 6 of 8
Hello World from thread 2 of 8
Hello World from thread 4 of 8
Hello World from thread 1 of 8
Hello World from thread 7 of 8
Hello World from thread 5 of 8
简单示例2
#include <omp.h>

#include <stdio.h>

  

int main(int argc, char *argv[]) {

  int sum = 0;

  int array[10] = {1,2,3,4,5,6,7,8,9,10};

  #pragma omp parallel for   /*for中的迭代变量i默认是私有的*/

    for (int i = 0; i < 10; i++) {

        sum += array[i];

    }

  

    printf("sum = %d", sum);

    return 0;

}

运行结果

sum = 55