OpenMP是一个应用程序编程接口(API),用于在不同平台上使用C、C++和Fortran语言进行独立于平台的共享内存并行编程。作为一个API,它在低级多线程原语上提供了一个高级抽象层。它的编程模型和接口可移植到不同的编译器和硬件体系结构,可在任意数量的CPU核心上扩展。因此,它适用的场景较为广泛,从具有几个CPU核心的台式PC到使用多达数百个核心的超级计算机中的计算节点。现代编译器(GCC 4.4+/Clang 3.8+)通常默认支持OpenMP,无需安装依赖库,使用方便。
OpenMP的基本理念是通过使用特殊的、类似注释的编译器指令(通常称为pragma)来增强顺序代码,向编译器提供如何并行化代码的提示。只需添加适当的pragma,就可以轻松地用于并行现有的顺序代码。
当遇到下面两种场景时,需要重新设计并行算法。
OpenMP采用fork-join的执行模式。开始只存在一个主线程,当需要进行并行计算时,派生出若干个分支线程来执行并行任务。当并行代码执行完成后,分支线程会合,并把控制流程交给单独的主线程。一个典型的fork-join执行模型如图1所示。
OpenMP最常用的是并行化for循环,下面以矩阵乘法为例,简单介绍用法。
并行作用域前定义的变量默认是公有的,并行作用域中定义的变量默认是私有的。紧跟制导语句的循环变量只能是私有的,检查并行作用域中的其它变量是否需要通过private显示私有化,避免出现竞争的情况。
在本例中,变量i、j、k、sum为私有变量,数组a、b、ans为不存在竞争的公有变量。
g++ -O2 -std=c++11 -fopenmp matrix_multiplication.cpp -o matrix_multiplication
OMP_NUM_THREADS=2 ./matrix_multiplication
本例在鲲鹏芯片上测试,当SIZE为3000时,串行执行时间56s。OpenMP两个线程并行执行,即0~1499与1500~2999次循环分别在两个线程中并行执行,执行时间为38s,性能提升明显。