也是 CS149 的准备内容,这次是 OpenMP 的初探。

1 OpenMP Introduction

OpenMP:跨平台、多语言(C、C++、Fortran) 、可扩展的并行计算 API,使得开发者可以轻松利用多核 CPU 的并行计算能力,加速程序的运行。

只需要在编译时加上 -fopenmp 选项即可开启 OpenMP 支持。

在程序中插入 #pragma omp 指令,编译器就会根据指令自动生成多线程代码,例如一个简单例子:

1
printf("Hello, World!\n");

在前面加上一句:

1
2
#pragma omp parallel
printf("Hello, World!\n");

程序就会根据硬件情况,在多个线程中执行 printf 语句。

OpenMP 也可以用于循环并行化,例如:

1
2
#pragma omp parallel for
for (int i = 0; i < 10; i++) { /* do something */ }

2 OpenMP Usage

OpenMP 的指令格式为 #pragma omp parallel [clause[ [, ]clause] ...],其中括号表示可选项,也就是可以有多个子句,每个子句可能有多个参数。下面列一些常见的指令:

  • #pragma omp parallel:创建一组线程(Team),指示下方 block 代码在每一个线程中并行执行

    • private(list):指定私有变量
    • shared(list):指定共享变量
    • default(shared | none):指定默认共享或私有
    • num_threads(n):指定线程数
    • if(expr):指定条件
    • copyin(list):指定复制变量
    • sections:配合 #pragma omp section 使用
  • #pragma omp for:指示下方 for 循环分配到 Team 中的线程并行执行(每个线程执行一部分,而不是每个线程执行整个循环)

  • pragma omp single:指示下方 block 代码只在一个线程中执行

  • #pragma omp simd:指示下方 for 循环可以用 SIMD 优化

  • #pragma omp section:将不同的 section 分配给不同的线程

  • #pragma omp parallel for:结合了 #pragma omp parallel#pragma omp for

    • collapse(n):指定 n 维循环进行并行化
  • #pragma omp critical:指示下方 block 代码只能由一个线程执行

  • #pragma omp barrier:等待所有线程到达 barrier

  • #pragma omp master:指示下方 block 代码只在 master 线程中执行

  • #pragma omp atomic:指示下方语句是原子操作

除了不同的指令之外,OpenMP 还提供了一些库函数,例如:

  • omp_get_thread_num():获取当前线程编号
  • omp_get_num_threads():获取线程总数
  • omp_get_max_threads():获取最大线程数
  • omp_get_num_procs():获取处理器数
  • omp_set_num_threads(n):设置线程数

以及锁相关的函数:

  • omp_init_lock():初始化锁
  • omp_destroy_lock():销毁锁
  • omp_set_lock():加锁
  • omp_unset_lock():解锁
  • omp_test_lock():尝试加锁

要了解更多 OpenMP 的用法,可以参考官方文档。

3 OpenMP Example

TODO


References:

Reference Guides - OpenMP

OpenMP 4.0 API C/C++ Syntax Quick Reference Card

OpenMP 3.1 API C/C++ Syntax Quick Reference Card