OpenMP语法与使用

简介

什么是OpenMP
Fork-Join模式

OpenMP API的三个要素
最小侵害性质
OpenMP 关键语法与概念列表

以下是 OpenMP 主要语法语句的功能简要说明,详细用法会在后面几节中叙述:

OpenMP 语法详解

程序编译
获取线程与计时
设置与获取线程
线程数的相关问题
  1. 如果不设置线程数呢?

    • OpenMP 默认使用以下规则:

      1)默认线程数 = 逻辑 CPU 核心数(例如,4 核 8 线程的 CPU 默认使用 8 线程,i7的是16)。

      2)若未设置 OMP_NUM_THREADS 环境变量且未调用 omp_set_num_threads(),运行时自动分配最大可用线程数。

      3)验证方法:可通过 unset OMP_NUM_THREADS 清除环境变量,程序将完全依赖默认值。

  2. 可不可以在并行区内部设置线程数?

    • 通常不能直接生效

      1)并行区域内的线程数在进入时已确定,调用 omp_set_num_threads() 不会修改当前区域的线程数。

      2)例外情况:若开启嵌套并行(设置 OMP_NESTED=TRUE),可在内部并行区域中通过 num_threads 子句或 omp_set_num_threads() 修改子区域的线程数。

      3)建议:在并行区域外部设置全局线程数,或通过 num_threads 子句直接指定当前区域的线程数。

  3. 如果两种方式设置的不同呢?

    • 优先级顺序(从高到低):

      1)if 从句。

      2)num_threads 子句(仅影响当前并行区域)。

      3)omp_set_num_threads() 函数(全局覆盖后续所有并行区域)。

      4)OMP_NUM_THREADS 环境变量(仅在程序启动时读取)。

      5)系统默认(一般是可用的处理器核数)。

    • 示例

      1)若环境变量设为 OMP_NUM_THREADS=4,但程序中调用 omp_set_num_threads(8),则实际使用 8 线程

      2)若同时在 #pragma omp parallel num_threads(2) 中指定子句,该区域强制使用 2 线程,其他区域仍用 8 线程。

  4. 如果在串行区请求omp_get_num_threads()?

    • 可以,但行为有特定规则:

      1)在并行区外调用:返回 0(主线程的默认ID)。

      2)在并行区内调用:返回当前线程的ID(0 到 omp_get_num_threads()-1 之间的整数)。

  5. 为什么只能获取、不能设置线程号?

    • 设计约束与线程管理机制

    1)唯一性与安全性:线程号由OpenMP运行时在创建线程组时自动分配,确保每个线程ID在团队内唯一且连续(0,1,2,…),避免手动设置导致冲突或错误。

    2)动态性:线程组可能因动态调度或嵌套并行而动态创建,手动设置线程号会破坏线程间的任务分配逻辑。

    3)抽象层封装:OpenMP隐藏了底层线程管理的细节,开发者只需关注任务划分,线程号仅用于区分线程身份。

获取时钟时间
并行区制导语句

并行区构造:parallel

计算例子:计算 π

循环工作构造:for
for循环构造:用于对循环进行多线程并行执行
线程调度
其他工作享构造
ordered从句与ordered构造
collapse从句
sections构造
single构造
任务构造
OpenMP任务构造
线程控制
动态线程
嵌套并行
flush构造
堆栈大小

同步构造

barrier构造:栅栏同步

single构造:有同步

master构造:无同步

critical构造

atomic构造
竞争条件和线程安全
程序的遗孤

持久变量

threadprivate 构造
全局或静态变量的传递与广播

向量化

OpenFOAM的simd构造
declare simd构造
编译器的自动向量化

从句汇总