【并行计算5】OpenMP
1、基本知识
OpenMP由Compiler Directives(编译指导语句)、Run-time Library Functions(库函数) 组成,另外还有一些和OpenMP有关的 Environment Variables(环境变量)、Data Types(数据类型)以及_OPENMP宏定义。
共享内存计算机上并行程序的基本思路就是使用多线程,从而将可并行负载分配到多个物理计算核心,从而缩短执行时间(同时提高CPU利用率)。在共享内存的并行程序中,标准的并行模式为fork/join式并行。
OpenMP下程序员只需要设计高层并行结构,创建及调度线程均由编译器自动生成代码完成。
而且最大的一个特点是,GPU也可以将其进行应用编写对应的程序。
2、具体语句结构
compiler directive 可以生成若干的thread,最后其实会变成low-level的pthread进行运作
- directive-name中do和for不能同时使用,directive-name通常只有一个,但parallel可以和do、for同时存在
-
clause条件option中,有default的参数,有private的参数,这些参数定义了对应data scope的使用范围,要通过看data的描述才能知道最后产生的data类型。且
clause是可以定义若干个的。
注意:
- 区分大小写;
- 跟在directives下的通常是一个block;
- “
#pragma omp parallel
”表示其后语句将被多个线程并行执行
3、OpenMP详细语句说明
PARALLEL REGION CONSTRUCT:Parallel
目的: create a teams of threads,这些thread执行的function call是完全相同的
最后其实是隐含着一个barrier,只有把线程全部做完之后才能继续执行
所以如果有一个thread结束,所有的thread就全结束了,是一起管理具体线程的
parallel区域是不能使用jump、goto语句
parallel region就是被struct block的区域
【1】IF clause 只会被master thread执行,判断是否满足条件进行执行
int a = 7;
#pragma omp parallel if(a) num_threads(6)
{
std::cout << omp_get_thread_num();
}
【2】num_threads(10),代表全部执行10个thread
【3】omp_set_num_threads(),在没写num_threads的clause时,就可以在层次码一开始进行书写即可,预先设定(有时候满足重复使用的需求)
【4】OMP_NUM_THREADS系统环境变量设定,在parallel region前运作
【5】默认情况默认的情况下去询问CPU进行对应执行,线程个数由系统预设(一般等于逻辑处理器个数,例如i5 4核8线程CPU有8个逻辑处理器)
常用的是omp_set_num_threads()
和OMP_NUM_THREADS
环境变量设定
而且可以嵌套使用parallel regionomp_get_nested()
检查是否嵌套omp_set_nexted(bool)
设置嵌套,其实也就是设置OMP_NESTED
环境变量为enable状态
如果说就不支持嵌套,那么在每个嵌套的并行区域中就只有一个线程被创建
WORK-SHAREING-STRUCTURE:do/for,section.single
1、 综述
想去规范thread去做load的分配,但是不管怎样,他们不会去lauch new thread
会与parallel在一起使用,甚至可以用for loop阿什么分配任务使用
其实也存在一个隐形的barrier去在整个结构的末尾
(除非用close去overwrite这个东西)
do/for->要共享loop去做
section->在core的level去做平行,每段thread可以做不同的任务,要把每个section一一写出来
section是不会重复做的。
single->section的特例:被包在其中的层次码,只有一个thread执行,因为有thread barrier所以其他线程不做但也等等这个thread去做,最好的适用状态就是IO。
2、 Do/for directive
去handle一个for loop,这里的关键是,每个线程执行的计算互不相同(操作的数据不同或者计算任务本身不同),多个线程协作完成所有计算。将C++ for循环的多次迭代划分给多个线程(划分指,每个线程执行的迭代互不重复,所有线程的迭代并起来正好是C++ for循环的所有迭代)
**注意:**使用for directive的两个条件:
1、C++ for复合特定限制
2、C++ for的各次迭代的执行顺序不影响结果的正确性(逻辑条件)
//通过例子中,我们可以看到for和parallel是并行使用的
const int size = 1000;
int data[size];
#pragma omp parallel
{
#pragma omp for
for(int i=0; i<size; ++i)//迭代1000次会被分成8短
data[i] = 123;
}
//但是其实是可以合并使用的parallel和for语句,是与上面语句等价的
const int size = 1000;
int data[size];
#pragma omp parallel for
for(int i=0; i<size; ++i)
data[i] = 123;
重要参数说明
- 【1】no-wait就是没必要等的话,提前做完的thread可以继续往下做,thread的生命周期不是Do/For而是parallel region的范围大小
-
【2】schedule决定到底哪些thread去做对应的任务
一个优秀的平行,它的突破口在于尽量的core做的任务balance
schedule(type[,size])
type有以下5种,size为chunk size的大小(每次分配给每个thread几个iteration)
- STATIC schedule(static, size)
可以放一个chunk size的值,可以一次性(固定的)让chunk数目的thread去做,减少schedule的动作,chunk size 过大可能不太合适会导致有的提前做完会等别人
- DYNAMICschedule(dynamic, size)
在run time决定chunk size,动态的调度,FCSF(先做完的先做任务,所以尽量保证balance整体的线程),也有chunk的argument,可以控制chunk,chunk size越大可能会更好一点,但chunk size是固定的,先做完的也是分配给其固定的chunk size大小的内容,但是问题来了其实我们想一开始chunk size大一点(减少schedule的花费),后来小一点(尽量平均早点完成对应的任务)也就是注意整体的balance
- GUIDED schedule(guided, size)
他和DYNAMIC比较相似,但是他的chunk size随着时间的变化逐渐变小,一开始的size是迭代数/线程数,但会以指数的方式(依次/2)下降到size,这里的size是分配后最终降到的size
- RUNTIMEschedule(runtime)
通过系统参数OMP_SCHEDULE,来决定OPENMP采用哪个最后(选择1、2、3中的任何一个)
- AUTOschedule(auto)
让compiler自动取决定,通常这种决定不好
如果提前知道chunk size
-【3】ordered因为希望结果和顺序结构的顺序一致,所以可以保证结束顺序(不建议),会有很多的时间消耗
-【4】collapse nested for loop,其实是collapse整个成一维的去协调做,但前提是这些每一层之间是没有数据依赖的,根据情况具体考虑问题,collapse的参数就是for loop的个数
DO/FOR EXAMPLE
3、 Sections directive
4、 Single directive
SYNCHRONIZATION CONSTRUCT
DATA SCOPE ATTRIBUTE CLAUSES
RUN-TIME LIBRARY ROUTINES
推荐阅读
-
迅雷上网加速器发布:提升物理带宽3~5倍
-
BB FlashBack Pro 5录像机采样率怎么设置?
-
vs2015/vs2013中mvc5 viewbag总是出现问题该怎么办?
-
安装会声会影X5时出现CRC错误提示媒体可能已损坏
-
你的企业还没做seo推广?我给你总结5点理由 非做不可
-
如何制作微信H5页面动画?Mugeda在线制作工具制作流程
-
惠普Pavilion x360变形笔记本发布 5月开卖
-
微信朋友圈怎么利用mugedaH5制作问候贺卡?
-
BB FlashBack Pro 5怎么录制动态视频?
-
免费开源文件压缩/解压管理工具7-Zip 15.06 Beta官方下载 支持RAR5格式文件