OpenMP
介绍
OpenMP 是一种应用程序接口 (API),可用于显式地指示多线程、共享内存并行性。
它由三个主要的 API 组件组成:
- 编译器指令
- 运行时库函数
- 环境变量
它是 Open Multi-Processing 的缩写,是一个应用程序接口(API),可用于显式指导多线程、共享内存的并行性。
在项目程序已经完成好的情况下不需要大幅度的修改源代码,只需要加上专用的 pragma 来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同 步互斥以及通信。
当选择忽略这些 pragma,或者编译器不支持 OpenMp 时,程序又可退化为通常的程序 (一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。
OpenMP 提供的这种对于并行描述的高层抽象降低了并行编程的难度和复杂度,这样程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节。对基于数据分集的多线程程序设计,OpenMP 是一个很好的选择。
共享内存模型
OpenMP 是为多处理器或多核共享内存机器设计的。底层架构可以是共享内存 UMA 或 NUMA。即 (Uniform Memory Access 和 Non-Uniform Memory Access)
因为 OpenMP 是为共享内存并行编程而设计的,所以它在很大程度上局限于单节点并行性。通常,节点上处理元素 (核心) 的数量决定了可以实现多少并行性。
基于线程的并行性
OpenMP 程序仅通过使用线程来实现并行性。
执行线程是操作系统可以调度的最小处理单元。一种可以自动运行的子程序,这个概念可能有助于解释什么是线程。
线程存在于单个进程的资源中。没有这个进程,它们就不复存在。
通常,线程的数量与机器处理器/核心的数量相匹配。但是,线程的实际 使用取决于应用程序。
Fork - Join 模型
OpenMP 使用并行执行的 fork-join 模型:
所有 OpenMP 程序都开始于一个主线程。主线程按顺序执行,直到遇到第一个并行区域结构。
FORK:主线程然后创建一组并行线程。
之后程序中由并行区域结构封装的语句在各个团队线程中并行执行。
JOIN:当团队线程完成并行区域结构中的语句时,它们将进行同步并终止,只留下主线程。
并行区域的数量和组成它们的线程是任意的。
数据范围
因为 OpenMP 是共享内存编程模型,所以在默认情况下,并行区域中的大多数数据都是共享的。
一个并行区域中的所有线程都可以同时访问共享数据。
OpenMP 为程序员提供了一种方法,可以在不需要默认共享范围的情况下显式地指定数据的“作用域”。
数据范围属性子句将更详细地讨论这个主题。
I/O
OpenMP 没有指定任何关于并行 I/O 的内容。如果多个线程试图从同一个文件进行写/读操作,这一点尤其重要。
如果每个线程都对不同的文件执行 I/O,那么问题就不那么重要了。