HetCompute Parallel Processing Tutorial(二)

一、并行编程模式

1)、并行计算模式是数据交互的并行编程容器。如果您的算法适合并行模式,则可以快速打包,因此您可以享受在平台上利用多种资源。并行编程模式描述了HetCompute并行模式。

2)、此外,HetCompute模式构建在基本API之上,用于创建和管理任务。因此,您可以构建自己的模式,并且它们将与HetCompute运行时系统的其余部分无缝地互操作。模式也可以与其他模式组合。例如,hetcompute::pipeline模式中的一个阶段可能包含任何其他HetCompute模式或其他HetCompute任务。

二、优化

1)、除了工作和数据的算法分解之外,并行程序需要调整到特定平台以实现最佳性能。 作为一般规则,应使用以下过程:

a、串行调整:应使用经典优化技术优化每个任务执行的代码:循环优化,强度降低和缓存局部性优化。

b、同步调整:协调并行执行通常被认为是开销 - 程序执行的附加指令不一定是有效工作的一部分。 这种开销包括关键部分中的序列化,等待依赖性被满足和/或条件变量被发信号通知等。经过精心调整的并行程序大部分时间都在执行工作而不是管理工作。 但是,可能需要复制计算以最小化同步。 使用HetCompute异步模式是避免同步的一种方法。

c、并行效率:当所有执行单元同样繁忙时,并行执行是最佳的,执行最少的冗余工作。 因此,平衡所有处理器的计算很重要。 这可以通过算法分解的组合来实现 - 更精细的粒度任务允许更好的负载平衡,并考虑架构特征,例如资源共享和产生任务的开销 - 更粗糙的粒度任务通常会产生更少的开销。 在HetCompute中,可以调整许多参数来控制执行模式的任务的粒度。

2)、缓存局部性

a、存在两种类型的存储器引用局部性,时间局部性,其中对给定存储器地址的程序引用在时间上聚集在一起,以及空间局部性,其中对相邻地址的程序引用在时间上聚集。缓存透明地利用两种类型的局部性:替换策略利用时间局部性,而宽缓存行和预取技术利用空间局部性。此外,当前的体系结构提供了几个级别的缓存,具有不同的共享模式。 例如,一级高速缓存(L1)通常在指令和数据之间分开,并且对于核心是私有的(在SMT架构的情况下由超线程共享),并且二级高速缓存(L2)由多个核共享。

b、虽然程序员无法直接控制缓存,但可以构建代码和数据以改善引用的局部性,从而有效地利用缓存机制。 在多核系统中,缓存是共享资源,因此程序员应该考虑以下内容:

(1)、一致性:大多数多核共享存储器系统提供硬件一致性。但是,体系结构实现了不同的一致性模型,从而影响了不同线程可以看到共享内存更新的方式。特别是,ARM体系结构定义了弱内存一致性模型。C++11标准定义了基元,以强制执行所有原子访问的内存操作顺序。高级程序员可以利用非顺序一致的排序来在这些系统上获得更好的性能。

(2)、虚假分享:当在两个不同核上同时执行的两个任务使用的独立数据项共同位于同一缓存行中时,会出现错误共享[19]。 因为一致性单元是高速缓存行,如果两个任务都访问了这些项,则该一致性协议将强制该行在高速缓存之间反弹。 通过使用诸如填充和/或分配到高速缓存行边界的技术将不同并发任务访问的数据项分离成单独的高速缓存行,可以避免错误共享。为了改善引用的局部性并限制内存碎片,程序员应该尽可能地将单个任务访问的数据项分组,最好是连续的内存地址块。

(3)、缓存干扰:在串行应用程序中,缓存优化被调整到整个缓存。但是,在并行应用程序中,高速缓存由执行单元共享。 经过精心调整的并行程序应通过确保重用真正的共享数据来最大限度地利用缓存。例如,通过维护只读共享数据的单个副本并同时引用它,可以利用时间局部性并最小化所使用的高速缓存量。为了最大限度地减少争用和干扰,任务的工作集大小应该适合缓存。考虑到共享缓存时的容量,必须调整平铺和缓存阻塞。

3)、最小化等待时间和同步

a、如上所述,高效的并行执行意味着在所有计算单元上平衡执行非冗余工作,同时最大限度地减少管理开销。串行执行(Amdahl定律)限制的部分显示并行应用程序在并行加速中的有效性。 因此,程序员应该仔细考虑序列化执行的不同因素,包括:

(1)、避免等待单个线程:长依赖链和/或经常等待单个任务的结果限制了应用程序中可用的并行度。HetCompute组可用于等待任务集,从而可能最大限度地减少拖延总量。

b、数据同步:步共享内存访问可能会引入相当大的序列化或缓存冲突开销。通过以下优化可以减少这种开销:

(1)、私有数据:共享数据的互斥分区。 例如,将图像分区为图块,其中每个任务在不同的图块上工作。 在分区不明显的情况下,程序员可以将共享数据复制到私有缓冲区,处理私有数据,然后将更改同步到共享副本。 并行缩减以及并行收集和分散操作有助于重塑私有和共享数据格式。

(2)、回避大型关键区块:由于关键部分保证互斥,因此它们会序列化访问这些区域的任务的执行。 最大限度地减少在关键部分中花费的时间,特别是在高度争用时,将减少同步开销。

(3)、使用原子操作:适当的内存排序进一步减少了同步开销,并依赖于硬件功能来实现高效的共享数据访问。

c、HetCompute鼓励异步编程风格。除了提供具有异步语义的并行编程模式之外,HetCompute的执行模型是将细粒度任务放置在依赖图中,从而最小化等待需求的模型。相比之下,fork-join模型产生了大量的工作,需要在控件从连接流出之前完成。异构并发在异构计算的情况下也是优选的,因为不需要阻止资源等待卸载设备完成工作。

4)、负载均衡

a、序列化是并行编程的潜在缺陷之一。另一个是所有计算单元的利用率不足。如果并行计算不平衡,则某些处理器将处于空闲状态,从而切入潜在的性能增益。为了避免这种情况,程序员应该注意平衡工作。这可以通过几种方式实现,最受欢迎的方式。

(1)、调整任务粒度:任务粒度表示任务中的工作量。理想情况下,如果已知工作量,可以手动平衡计算。但是,对于不规则应用程序不是这种情况,在这种情况下,过度分解和依赖HetCompute运行时动态调度是更好的选择。任务粒度在管理开销方面也起着重要作用。随着任务粒度的降低,管理并行执行的开销将占总时间的一小部分。因此,较粗略的任务是优选的,以最小化开销。这是程序员需要权衡的重要平衡。通过提供一组灵活的API来创建任务,HetCompute可以轻松探索这些权衡。

(2)、过度分解:过度分解是程序员确保系统中有足够的并行工作的机制,因此运行时总是有工作量来安排。过度分解被定义为创建比可用计算单元的数量更多的任务,使得如果任务阻塞或等待依赖性被满足,则其他独立任务继续进行。 提供的独立任务越多,可以实现的负载平衡越好。当然,需要考虑任务粒度并管理开销。

5)、结论

a、并行编程很有趣,而且在智力上具有挑战性。 构建并行应用程序时有许多因素可以发挥作用,这可能并不明显。本教程中描述的技术将帮助您实现并行编程的主要目标 - 加速应用程序的执行。HetCompute旨在简化此任务并提供便于表达并行计算的抽象。创建并行算法的艰苦工作仍然存在;但是,HetCompute和这些技术将有助于将这些算法编码成一个有效的解决方案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值