我们先前的程序设计均是在单核计算范围内,应付小型计算尚可,当模型是大规模自由度时,计算成本大大增加,多核并行计算是提升计算速度的重要方法,对于大型计算平台,如云计算,都是基于并行计算理论,所以了解并行计算,对于计算速度的提升有着很大的裨益。
OpenMP用于共享内存并行系统的多处理器程序设计的一套指导性的编译处理方案,支持的语言包括C/C++和Fortran。本文将将要说明OpenMP的用法,带着大家初步认识并行计算。
Option-Project-Complier Flags,在Fortran Compiler和Linker输入- fopenmp。
program main
PRINT'(a)','Hello 1'
!$OMP PARALLEL
PRINT'(a)','Hi'
!$OMP END PARALLEL
PRINT'(a)','Hello 2'
end program
图 1:并行计算示意图
输出结果:Hello 1 ;Hi Hi Hi Hi Hi Hi Hi Hi; Hello 2.
以上程序中,以!$OMP PARALLEL
和!$OMP END PARALLEL
封装需要并行计算的代码块,该程序用默认线程数(系统能够提供的CPU总核数,即8个CPU线程)输出了8个“Hi”,我们可以用以下方法查看个人笔记本CPU总核数。
方法1:“Ctrl+Alt+.”打开任务管理器,性能-CPU,显示多少个框框,就表示计算机有多少CPU核数。
图 2:查看CPU核数方法 1
方法2:右击此电脑-管理-设备管理器-处理器,显示多少个处理器,就有多少个CPU核心数。
图 3:查看CPU核数方法 2
program parallel
implicit none
include 'omp_lib.h'
integer :: tid,mcpu
call OMP_SET_NUM_THREADS(3)
tid = OMP_GET_THREAD_NUM()
mcpu = OMP_GET_NUM_THREADS()
print'(a,i4,a,i4,a)','Hello from thread',tid,' in',mcpu,' CPUs'
print'(a)','---------------before parallel------------------'
print *
!$OMP PARALLEL DEFAULT(NONE) PRIVATE(tid,mcpu)
print'(a)','---------------during parallel------------------'
tid = OMP_GET_THREAD_NUM()
mcpu = OMP_GET_NUM_THREADS()
print'(a,i4,a,i4,a)','Hello from thread',tid,' in',mcpu,' CPUs'
!$OMP END PARALLEL
print *
print'(a)','---------------after parallel-------------------'
print'(a,i4,a,i4,a)','Hello from thread',tid,' in',mcpu,' CPUs'
end program parallel
注意:
1. include 'omp_lib.h'
是对OpenMP库函数的声明,如此一来。程序中不用再定义其数据类型;
2. 并行计算之前,即!$OMP PARALLEL
语句之前,程序处于串行区,仅有一个线程(编号为0)控制,实际使用的进程数为1;
3. 库函数
1. OMP_SET_NUM_THREADS(3)
作用是设置在并行区域内允许使用的线程总数(<=CPU总数);
2. OMP_GET_THREAD_NUM()
返回当前线程的线程号;
3. OMP_GET_NUM_THREADS()
返回执行并行块所使用的线程总数;
4. 并行区域输出结果:Hello from thread 1 in 3 CPUs Hello from thread 0 in 3 CPUs Hello from thread 2 in 3 CPUs子线程编号的顺序具有随机性。
5. 子线程编号均赋值为tid
,但是编号却不相同,因此需要DEFAULT(NONE)
指定是共享变量还是私有变量,采用PRIVATE(tid,mcpu)
声明tid
和mcpu
为私有变量。
推荐书籍:
[1] 雷洪. 多核并行高性能计算OpenMP[M].冶金工业出版社, 2016