目录
- 什么是OpenMP
- OpenMP的工作原理
- Amdahl 定律
- Gustafson 定律
- openmp的库在ubuntu下的编译
什么是OpenMP
OpenMP(Open Multi-Processing)是一种并行编程框架,用于在共享内存系统中实现并行计算。它是GCC编译器的一部分,提供了一组指令和编译器指导,帮助程序员实现程序的并行化。OpenMP的目标是简化并行编程,提高程序的执行效率。
OpenMP的工作原理
OpenMP使用线程级并行化来实现程序的并行运行。它通过创建多个线程来执行程序的不同部分,同时使用同步机制来管理线程之间的数据共享和任务调度。OpenMP的并行指令和编译器指导帮助程序员标识和管理并行任务,以实现程序的并行化。
Amdahl 定律
total
=
1
(
1
−
P
)
+
P
N
{\text{total}} = \frac{1}{(1 - P) + \frac{P}{N}}
total=(1−P)+NP1
其中total是总的加速比,P 是可以并行化的部分的比例,N 是并行化之后的处理器数量。
考虑这样一种情况,系统的某个部分初始耗时比例为 60%(a=O. 6),其加速比例因子为 3(k=3) 。则我们可以获得的加速比为 1/[0. 4+0. 6/3]=1. 67 倍。虽然我们对系统的一个主要部分做出了重大改进,但是获得的系统加速比却明显小于这部分的加速比。这就是 Amdahl 定律的主要观点 要想显著加速整个系统,必须提升全系统中相当大的部分的速度。
。
Gustafson 定律
古斯塔夫森定律也是在表明处理器个数、并行比例和加速比之间的关系。
执行时间: 串行时间a + 并行时间b
优化后时间: a + nb、
加速比: (a + nb) / (a + b)
f串行比例 : a / (a + b)
如果串行比例很小,那个加速比就是处理器的个数。
现在来考虑阿姆达尔定律基于这些假设估计的加速比。 假设串行执行的百分比是 1%,阿姆达尔定律等式得出 1/(0.01 + (0.99/32)) = 24.43X。 这是个错误计算,因为给定的串行时间百分数与 32 内核执行有关。 该示例没有指出对于更多或更少的内核(甚至只有一个内核),对应的串行执行百分数将是多少。 如果代码扩展完美,并且数据大小与内核数同时扩展,那么该百分数能够保持不变,阿姆达尔定律计算的结果将是 32 内核上(固定大小)单核问题的预测加速比。
运用斯塔夫森定律时,必须知道并行执行期间串行时间的百分数,因此该公式的一个典型用例是计算扩展的并行执行(数据集大小随着内核数量的增加而增加)与相同大小问题串行执行的加速比。
在极少数情况下,应用的加速比大于内核数。 这种现象被称为超级线性加速。 发生超级线性加速的典型原因是固定大小数据集被分解得足够小(对内核而言),可以放入本地高速缓存。 当以串行方式运行时,数据必须通过高速缓存获取,在获取期间处理器只能等待。 如果数据足够大,需占用清空之前使用的某些高速缓存行,那么后续对这些高速缓存行的任何复用都会导致处理器再次等待。 当数据被分解成可放入内核上高速缓存的数据块时,一旦这些数据被全部存入高速缓存,则无需经历复用高速缓存行所带来的等待复用。 因此,使用多个内核可以消除在单个内核上与串行代码执行相关的一些系统开销。 这样,过小的数据集(小于一般的数据大小)便会产生性能提升的错觉。
OpenMP可应用于各种计算密集型任务。例如,我们可以使用OpenMP来并行化图像处理任务,如图像滤波和特征提取。我们还可以使用OpenMP来并行化矩阵运算,如矩阵乘法和矩阵求逆。此外,OpenMP还可以应用于机器学习任务,如并行化训练和推理过程。
openmp的库在ubuntu下的编译
openmp库都是随编译器一起发布的,如果你的程序是源代码编译的,只要编译器支持openmp编译选项就肯定能用。
在cmakelist中添加:
FIND_PACKAGE( OpenMP REQUIRED)
if(OPENMP_FOUND)
message("OPENMP FOUND")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif()
在c++文件中添加头文件:
#ifdef _OPENMP
#include <omp.h>
#endif
完整的主程序如下:
#include <iostream>
#ifdef _OPENMP
#include <omp.h>
#endif
using namespace std;
int main()
{
#if _OPENMP
cout << " support openmp " << endl;
#else
cout << " not support openmp" << endl;
#endif
return 0;
}