|
|
|
|
移动端

2.4.5 线程级并行

《高性能并行珠玑:多核和众核编程方法》第2章从正确到正确&高效:Godunov格式的Hydro2D案例学习,本章将探讨一段科学模拟代码,这段代码是一个以气体动力学为基础的模拟程序。这份程序的输出结果正确,但(初始版本)性能欠佳。本节为大家介绍线程级并行。

作者:张云泉 等译来源:机械工业出版社|2017-11-14 17:44

技术沙龙 | 6月30日与多位专家探讨技术高速发展下如何应对运维新挑战!


2.4.5 线程级并行

在参考代码中,线程级并行只发生在slab的y维度上(或者“高”维度)(回想图2-6),这对并行有很大限制。

slab调度策略中在存储、通信和负载均衡上的消耗表明原始方案并不如意,需要改进。我们将参考代码转换为称为块(tiling)的域分解方法。参考图2-12,这是一个图片解释。

仿真网格沿着x和y维度被切割成一系列矩形小块,这些小块被分配给线程。这个调度方案并不要求一对一的线程与块的映射,但是我们现有的实现只支持一对一的情况。每个小块对于它的子域、维度、stride和其他需要记录的信息,有一套独立分配的一套解和变量(参见图2-13)。

halo区。每个小块维护了四个halo区(在x和y方向上分别有两个halo块),这些区域的宽度是2,这有利于提升块与块间的通信效率和应用边界条件(将这个条件应用到和原始网格共享边的块上)。这就是在块中的{x,y}_{y,var}stride和{x,y}_edges域。

每个块和它们自己的网格(有更小的维度)有相同的运行模式;更新时使用与其所在网格相同的顺序,同时每个块分别独立计算x轴和y轴遍历。当一个遍历运算完成时,有必要通过使用send_{low,high}_{x,y}_edge()函数使用最新的积分数据更新它们临近的单元格。在x轴遍历开始之前,x halo必须被交换。同样,在y轴遍历开始前,y halo也必须被交换。时间步长计算作为x轴遍历在奇数时间步中的一部分将在本地完成,而且规约要在所有的块间实现(见图2-14~图2-16)。

减少通信。为了最小化通信开销和块间的伪分享问题,我们分配每个halo区时,让它们与自己和其他块不共享缓存块。然后,在每个通信阶段,每个块将复制它自己的边域(宽度是2)给对应的邻居。

线程必须明确它们之间的通信以协调halo区域的交换和计算固定时间步长;为了尽可能避免每次遍历的全局同步,每个线程在一个块上工作时,这个块只通过点对点的同步与其他邻居块上工作的线程同步。甚至固定时间步长的计算中全局归约可以用避免通信的树形归约来实现。

点对点同步和树形归约对于交叉开关阵列和少数的多核系统的影响不是那么大,但是全局栅栏的代价是随着处理器的数量以O(logn)的量级增长的,随着越来越多的内核搭载到处理器上,其性能可能将会因为非一致内存访问(NUMA)而受到更大的影响。交换缓存和halo区是有存储代价的,不过对于一个大规模网格来说这些代价是微不足道的,甚至,在一个240线程的协处理器上这些消耗也是非常小,同时,相比于slab所需要的大规模中间存储,这些消耗也很小。

继续优化。刚刚提到的优化结果(相比于参考代码)在图2-17中呈现。相对于图2-8中参考代码的性能,这展示了对于处理器和协处理器使用固定时间步,旋转更新和块的

应用之后,优化后代码的性能(用时间作为参考量)。到此为止,处理器的性能提高了2~3.3倍和协处理器的性能提高了2.3~3.6倍。这表明在这个计算环境中,合理使用线程和内存子系统可以在代码和架构上有更多收益。就像我们马上要看到的,我们将会得到更多有益的东西。



喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

WebWork in Action中文版

本书是一本从头至尾都使用现实世界例子讲述有关编写Web应用程序的书籍。WebWork所强调的内容是:利用框架实现你的项目,而不是被框架所阻碍...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊