并行计算中的数据分区与循环并行化技术
在并行计算领域,数据分区和循环并行化是提高程序性能的关键技术。本文将探讨多分区数据分布的编译器支持以及部分并行循环的推测并行化技术。
多分区数据分布的编译器支持
在并行化编译器中,常见的数据分布方式有广义块分布及其变体。例如,HPF2 标准中规定的通用 BLOCK 分布,它将数组划分为大小可能不等的矩形块,并为每个处理器分配一个块。而多分区则为每个处理器分配多个大小相同的块。
在 Rice dHPF 编译器中,已经实现了对多分区的支持。虽然目前端到端的性能和可扩展性还不尽如人意,但多分区带来的更好的并行性、负载均衡和粗粒度通信,有望在改进代码生成策略以解决性能问题后,产生更优的编译器生成代码。
此外,对多分区的支持是构建支持过度分区的通用框架的基础。过度分区有一系列额外的应用,比如未来可以将其作为生成适用于广域计算网格的多线程、低延迟程序的基础。而且,dHPF 编译器对过度分区的支持与现有的复杂分析和代码生成技术基本正交,这得益于基于整数元组集合操作的抽象分析和代码生成框架。即使采用多分区,dHPF 编译器仍能利用复杂的并行化策略,如非所有者计算分区和部分计算复制,以减少通信。
部分并行循环的推测并行化
当前的并行化编译器难以识别大量可并行化的循环,因为这些循环的访问模式复杂或静态定义不充分。之前提出的方法是将循环作为 doall 进行推测执行,并应用完全并行的数据依赖测试来确定是否存在跨处理器依赖。如果测试失败,则串行重新执行循环。这种方法虽然能很好地利用 doall 并行性,但对于存在跨处理器流依赖的循环会导致性能下降,而且未充分利用循环现有的部分并行性。
为了解决这些问题,提出了递归 LRPD 测试技术。该技术可以提取和利用任何循环的最大可用并行性,并将潜在的性能下降限制在运行时依赖测试的开销上,即消除了因错误并行执行而损失的时间。对于完全串行的循环,其渐近时间复杂度等于顺序执行时间。
递归 LRPD 测试的原理
递归 LRPD 测试是对推测 doall 并行化技术的扩展。在执行过程中,将部分并行循环转换为一系列完全并行的循环。在每个阶段,并行推测执行所有剩余的迭代,并应用 LRPD 测试来检测潜在的依赖关系。所有正确执行的迭代(即第一个检测到的依赖关系之前的迭代)将被提交,然后对剩余的迭代递归执行该过程。
具体来说,当编译器无法静态确定共享数组的访问模式时,会分配用于标记写访问和读访问的影子数组。循环会增加标记代码,并封装在一个 while 循环中,重复进行推测并行化,直到循环成功完成。在每次推测执行后,会分析标记结果,将已计算的元素从私有存储复制到共享存储,并恢复可能被修改的数组状态。如果检测到跨处理器依赖,需要重新初始化影子数组和私有数组,并对剩余的迭代重新执行 LRPD 测试。
两种执行策略
在递归 LRPD 测试中,有两种执行策略可供选择:
-
不重新分配数据(NRD)
:如果每次迭代的有用计算成本 ω 小于等于数据重新分配成本 ℓ 与屏障同步成本 s 之和,即 ω ≤ ℓ + s,那么在检测到依赖后不重新分配剩余的迭代是更合适的选择。在这种情况下,并行执行的总时间可以通过公式 $T_{static}(n) = \sum_{i=0}^{k_s} (\frac{n\omega}{p} + s) = \frac{n\omega k_s}{p} + k_s s$ 计算,其中 $k_s$ 是完成推测并行化所需的步骤数,$p$ 是处理器数量,$n$ 是迭代次数。
-
重新分配数据(RD)
:如果 ω > ℓ + s,那么在检测到依赖后重新分配剩余的迭代可能更有利。此时,并行执行的总时间为 $T_{dyn}(n) = \sum_{i=0}^{k_d} (\frac{n_i\omega}{p} + \frac{n_i\ell}{p} + s) = \frac{(\omega + \ell)}{p} \sum_{i=0}^{k_d} n_i + k_d s$,其中 $n_i$ 是第 $i$ 次推测并行化开始时剩余的迭代次数,$k_d$ 是使用重新分配时完成的推测并行化步骤数。
然而,即使重新分配最初有用,也存在一个应该停止的点。具体来说,只要每个处理器上用于有用计算的时间大于重新分配和同步的开销,就应该进行重新分配。即满足 $n_{k_d} \geq \frac{ps}{\omega - \ell}$ 时进行重新分配。
为了更好地理解这两种策略,下面通过一个表格进行对比:
| 策略 | 适用条件 | 优点 | 缺点 |
| — | — | — | — |
| NRD | ω ≤ ℓ + s | 实现简单,避免了数据重新分配的开销 | 对于某些情况可能导致执行时间较长 |
| RD | ω > ℓ + s | 充分利用处理器资源,减少每个阶段的执行时间 | 可能会发现新的跨处理器依赖,增加远程缓存缺失的开销 |
性能模型分析
为了更有效地进行推测并行化,根据循环的依赖分布将循环分为两类:
-
几何(α)循环
:在每次推测并行化步骤中,完成当前剩余迭代的恒定比例(1 - α)。
-
线性(β)循环
:在每次推测并行化步骤中,完成原始迭代的恒定比例(1 - β)。
对于不同类型的循环,在不同策略下的执行时间计算方式不同。例如,对于几何循环,在 RD 策略下,$n_i = n\alpha^i$,$\sum_{i=0}^{k_d} n_i = n \frac{\alpha^{k_d + 1} - 1}{1 - \alpha}$,$k_d = \log_{\alpha} [(\frac{s}{\omega - \ell}) \frac{p}{n}]$,$k_s = \log_{\frac{1}{\alpha}} p$,总时间 $T(n) = \frac{n}{p} (\omega + \ell) \frac{\alpha^{k_d + 1} - 1}{1 - \alpha} + \frac{n\alpha^{k_d}\omega k_s}{p} + (k_d + k_s) s$。
通过对一个合成循环在 HP - V2200 系统的 8 个处理器上进行实验,验证了不同策略的性能。实验结果表明,自适应重新分配策略在性能上表现较好,而 NRD 策略表现最差。但需要注意的是,实验中的合成循环假设 α 和 β 是常数,在实际应用中,需要在 R - LRPD 测试的每个阶段调整模型参数。
下面是递归 LRPD 测试的简单流程图:
graph TD;
A[开始] --> B[初始化影子数组和状态];
B --> C[并行推测执行循环];
C --> D[进行 LRPD 测试];
D -- 成功 --> E[提交结果,结束];
D -- 失败 --> F[数据恢复和重新初始化];
F --> G[根据策略决定是否重新分配数据];
G -- 是 --> H[重新分配数据,更新参数];
G -- 否 --> I[不重新分配数据,更新参数];
H --> C;
I --> C;
综上所述,多分区数据分布和递归 LRPD 测试技术为并行计算中的循环并行化提供了有效的解决方案。通过合理选择数据分布方式和执行策略,可以提高程序的性能和可扩展性。未来的研究可以进一步优化这些技术,以适应更复杂的应用场景。
并行计算中的数据分区与循环并行化技术
递归 LRPD 测试的实际应用与优化
在实际应用中,递归 LRPD 测试技术需要根据不同的场景进行优化。以下是一些常见的实际应用情况和相应的优化方法:
复杂访问模式的处理
在许多实际程序中,循环的访问模式可能非常复杂,静态分析难以确定其并行性。递归 LRPD 测试可以有效地处理这类情况。例如,在科学计算中,一些算法的数组访问模式可能依赖于输入数据,编译器无法在编译时确定其是否可以并行执行。通过递归 LRPD 测试,可以在运行时动态地检测并行性,将部分并行循环转换为完全并行的循环。
为了优化复杂访问模式下的性能,可以采用以下方法:
-
动态负载均衡
:在递归 LRPD 测试中,由于每次执行可能会有不同数量的迭代完成,因此可以采用动态负载均衡技术,根据每个处理器的执行情况动态地调整任务分配。例如,使用动态反馈引导调度,在每次迭代完成后,根据处理器的空闲情况重新分配剩余的迭代。
-
减少影子数组开销
:影子数组用于标记读写访问,在处理大规模数据时,影子数组的开销可能会成为性能瓶颈。可以考虑采用压缩影子数组的方法,减少内存占用。例如,使用位图或哈希表来表示影子数组,而不是使用完整的数组。
多线程环境下的应用
在多线程环境中,递归 LRPD 测试同样可以发挥作用。多线程程序中的循环可能存在复杂的依赖关系,通过递归 LRPD 测试可以有效地提取并行性。在多线程环境下,需要考虑以下几个方面的优化:
-
线程同步
:在并行执行过程中,线程之间需要进行同步操作,以确保数据的一致性。可以采用细粒度的同步机制,减少同步开销。例如,使用锁粒度控制,只在必要时进行加锁操作。
-
数据局部性
:为了提高缓存命中率,需要优化数据的局部性。可以采用数据预取技术,提前将数据加载到缓存中。例如,在循环执行前,根据访问模式预测需要的数据,并提前加载到缓存中。
性能评估与比较
为了评估递归 LRPD 测试技术的性能,需要进行详细的实验和比较。以下是一些性能评估的指标和比较方法:
性能指标
- 执行时间 :是衡量程序性能的最直接指标。通过比较不同策略下的执行时间,可以评估递归 LRPD 测试的性能。
- 加速比 :加速比是并行执行时间与串行执行时间的比值。加速比越高,说明并行化效果越好。
- 可扩展性 :可扩展性是指随着处理器数量的增加,程序性能的提升程度。一个好的并行化技术应该具有良好的可扩展性。
比较方法
可以将递归 LRPD 测试与其他并行化技术进行比较,例如传统的静态数据依赖分析方法和简单的推测 doall 并行化方法。通过在不同的测试用例上进行实验,比较它们的性能指标。
以下是一个简单的性能比较表格:
| 技术 | 执行时间 | 加速比 | 可扩展性 |
| — | — | — | — |
| 递归 LRPD 测试 | 低 | 高 | 好 |
| 传统静态分析 | 高 | 低 | 差 |
| 简单推测 doall | 中 | 中 | 中 |
总结与展望
本文介绍了多分区数据分布和递归 LRPD 测试技术在并行计算中的应用。多分区数据分布为并行化编译器提供了一种新的数据分布方式,能够提高并行性和负载均衡。递归 LRPD 测试技术则可以有效地处理部分并行循环,提取最大可用并行性,并减少潜在的性能下降。
在实际应用中,递归 LRPD 测试技术需要根据不同的场景进行优化,如处理复杂访问模式和多线程环境。通过性能评估和比较,可以发现递归 LRPD 测试技术在性能和可扩展性方面具有明显的优势。
未来的研究可以进一步探索以下方向:
-
更复杂的依赖关系处理
:目前的递归 LRPD 测试主要处理跨处理器依赖,对于更复杂的依赖关系,如循环嵌套中的依赖关系,可以进一步研究和优化。
-
与其他并行化技术的结合
:可以将递归 LRPD 测试与其他并行化技术,如自动并行化框架和任务并行化技术相结合,以提高并行化的效果。
-
自适应策略的优化
:在实际应用中,不同的程序和输入数据可能需要不同的执行策略。可以研究自适应策略,根据程序的运行情况自动选择最优的执行策略。
以下是一个总结递归 LRPD 测试流程的 mermaid 流程图:
graph LR;
A[开始] --> B[初始化];
B --> C{是否完成};
C -- 否 --> D[并行推测执行];
D --> E[LRPD 测试];
E -- 成功 --> F[提交结果];
E -- 失败 --> G[数据恢复];
G --> H{是否重新分配数据};
H -- 是 --> I[重新分配];
H -- 否 --> J[不重新分配];
I --> D;
J --> D;
F --> C;
C -- 是 --> K[结束];
通过不断地研究和优化,这些技术有望在未来的并行计算中发挥更大的作用,为高性能计算提供更强大的支持。
超级会员免费看
1985

被折叠的 条评论
为什么被折叠?



