并行与分布式计算:OpenMP编程中的任务结构与分解(四)
新的一轮MPI作业已经发布,我尽量在DDL之前给同学们把MPI部分也更新出来!鱼生苦短,争取更咸!
Section 4 OpenMP编程中的任务的分解与分配
尽管Foster的设计原则倡导我们要进行四个设计步骤,但实际上OpenMP编程中往往先考虑的是任务的分解和分配。分解就是决定哪一部分先执行哪一部分后执行,哪一部分可以并行,哪一部分只能交给单线程;分配就是决定可以并行的任务部分如何分配给不同的处理器,如何权衡并行程度与通讯开销。
任务的分解
同一项工作可以被分解成很多种子任务的组合,不同的分解可能产生多种多样的计算方式和安排方式
并行度(degree of concurrency)
定义:可并行的任务数目
- 在程序执行中可能发生变化
指标:
- 最大并行度:在程序执行过程中,并行任务数的最大值
- 平均并行度:同时并行任务(关于时间的)平均数
并行度与任务粒度(granularity)
- 两者处于敌对关系,如果任务分的极为细致,那么并行度很高,任务的粒度就很低,如果任务分的笼统,那么粒度很大,并行度却很低
- 既要有一定的并行度,以提高效率,也要保证一定的任务粒度,减少代码工作、增强直观可读性
任务依赖关系图
任务依赖关系图反映的是任务间的拓扑关系。一个任务只有等待指向它的所有前置任务都完成才能开始执行
关键路径(重要)
任务依赖关系图(一个有向连通无环图)中的边展示了任务的拓扑关系(前后关系)
-
关键路径:最长权重的路径
- 关键路径长度决定了并行程序执行时间的下界
任务交互图(Task Interaction Graph)
注意与任务依赖关系图(Task Dependency Graph)区分,任务交互图展现的是任务间的数据交互关系
- node=task
- edge=interaction or data exchange
并行效果
限制并行效果的因素
- 最小任务粒度(与并行度、任务交互都有关系)
- 任务间的依赖关系
- 并行开支(比如任务间通讯的开销)
- 工作中不能并行化的比例
衡量并行效果的指标
- (单线程时间/p线程时间)
任务的分配
任务、线程与映射
实际操作中将任务分配给threads,而不是cores,threads到cores的映射由OS完成
- 将tasks分配给threads的映射对于并行程序的效果来说是至关重要的
借助什么工具选择映射
- 试图将独立的任务分配给不同线程时:使用任务依赖图
- 最少的线程闲置
- 最优的负载均衡
- 试图让线程间交互最少时:使用任务交互图
- 最少的通讯消耗
一个最好的映射一定要最小化并行执行时间
- 将不相互依赖的任务映射给不同线程
- 将关键路径上的任务尽快映射给线程
- 最小化线程间的通讯
- 实际上这些原则一般会彼此冲突,例如不分割任务使得交互最少,但完全没有加快速度