
1. 项目概述CPU-GPU异构系统中的内存调度挑战在当今的高性能计算、AI训练和图形渲染领域CPU-GPU异构系统已经成为主流架构。这种架构的核心优势在于CPU擅长处理复杂的串行逻辑和控制流任务而GPU则专为大规模并行计算设计。为了最大化协同效率现代系统级芯片SoC越来越多地采用统一内存架构UMA让CPU和GPU共享同一片物理内存。这听起来很美数据无需在CPU内存和GPU显存之间来回搬运理论上能显著降低延迟、简化编程模型并节省功耗。苹果的M系列芯片、AMD的APU以及许多移动SoC都采用了这种设计。然而理想很丰满现实却很骨感。当CPU和GPU这两个“性格迥异”的计算单元开始共享同一块内存时问题就来了。内存控制器就像是一个繁忙的十字路口而CPU和GPU应用则是源源不断驶来的车辆。GPU应用尤其是那些进行大规模矩阵运算或图形渲染的任务会以极高的频率、海量的规模产生内存请求就像一支由无数摩托车组成的车队瞬间就能塞满整个路口。相比之下CPU应用的内存请求虽然频率较低但对延迟极其敏感就像需要紧急通行的救护车。如果按照传统的“先到先服务”或“行缓冲命中优先”的调度策略GPU的“摩托车队”会长时间霸占内存通道导致CPU的“救护车”被严重阻塞整体系统性能尤其是CPU的性能会因此大幅下降。这就是我们面临的核心挑战在CPU-GPU异构系统中如何设计一个高效、公平且硬件实现简单的内存调度器来协调两者对共享内存的访问从而在提升系统整体吞吐量的同时保障对延迟敏感的CPU应用的性能本文要深入探讨的正是我们团队针对这一问题所提出的一种解决方案感知与预测批处理Perceptual and Predictive Batch-Processing, PPBP内存调度策略。这个策略的核心思想不是去发明一个全新的、复杂的调度算法而是基于对系统运行时状态的“感知”和“预测”对现有的成熟调度方法进行智能化的“批处理”改造。我们的目标很明确用尽可能低的硬件开销显著降低CPU与GPU之间的内存访问干扰特别是保护CPU应用的性能不受GPU“洪流”的冲击。2. 核心思路与方案选型为何选择感知预测与批处理在深入PPBP的细节之前我们先来拆解一下解决这个问题的几种常见思路并解释为什么我们最终选择了感知预测与批处理相结合的道路。2.1 现有调度策略的局限性传统的异构系统内存调度研究大致可以分为几个方向基于源分离的调度最直观的想法是把CPU和GPU的请求彻底分开。例如分段内存调度器SMS或关键性感知内存调度CAMS会为CPU和GPU设立独立的请求缓冲区或虚拟通道。这种方法确实能隔离干扰但它带来了新的问题硬件资源如缓冲区需要被静态或半静态地划分缺乏弹性。当一方请求少而另一方请求多时会造成资源浪费并且增加了硬件设计的复杂性。基于动态优先级的调度这类方法试图动态分析GPU的执行进度并据此调整其内存访问优先级。例如如果GPU的渲染进度落后于预期就提高其优先级在渲染末期则让GPU优先访问。另一种思路如CLAMS是评估GPU核心的“延迟容忍度”——如果一个GPU核心有很多可以切换执行的线程称为warp来隐藏内存延迟那么它对单次内存访问的延迟就不那么敏感优先级就可以调低。这些方法在理论上很精巧但问题在于它们通常需要深入GPU核心内部去收集复杂的运行时状态信息比如每个核心有多少个活跃的warp、多少warp在等待内存。获取这些信息的硬件监控电路非常复杂在真实的芯片设计中实现成本高昂甚至不切实际。经典调度算法的直接应用很多实际机器仍在使用的第一就绪先来先服务FRFCFS算法在异构环境下表现很差。因为它会优先服务行缓冲命中的请求而GPU请求由于空间局部性强极易产生连续的命中从而长时间霸占内存带宽。2.2 PPBP的设计哲学在简单与有效之间寻找平衡我们的设计出发点基于两个关键观察干扰的本质是交错CPU和GPU性能下降的主因是它们的内存请求在内存控制器处被高度交错地处理。这种交错破坏了各自访问的空间局部性导致行缓冲命中率暴跌我们的模拟显示CPU应用行缓冲命中率可能下降23%-35%。预测可以简化虽然精确获取GPU内部状态很难但我们可以通过一个“外部视角”来间接推测。内存控制器的请求缓冲区里本身就包含了来自GPU的请求。这些请求的数量和“线程ID”的多样性能否反映GPU内部的繁忙程度和延迟容忍度呢基于此PPBP选择了以下技术路径感知Perceptual我们放弃侵入GPU核心的复杂监控转而只感知内存控制器请求缓冲区中可见的、易获取的信息CPU请求数量、GPU请求数量、以及当前缓冲区中来自GPU的不同线程数量。预测Predictive利用感知到的历史信息一个时间周期内的GPU线程数结合帕累托分布的特性来预测GPU整体的活跃线程规模进而估算其延迟容忍度。这是一种用“外部可见结果”倒推“内部状态”的轻量级方法。批处理Batch-Processing根据预测出的GPU延迟容忍度动态决定在接下来的一小段时间我们称为一个“量子”内是批量处理CPU请求还是GPU请求。在这段时间内调度器只服务单一类型的请求从而在微观上创造“不交错”的访问窗口保护各自的空间局部性。这个方案的核心优势在于其极低的硬件复杂性和良好的可实现性。它不需要修改GPU核心只需要在内存控制器侧增加几个计数器和简单的逻辑单元就能实现智能调度。下面我们就来拆解PPBP的具体实现。3. PPBP调度策略的三大核心环节详解PPBP策略的执行可以清晰地分为三个阶段感知、预测、批处理调度。这三个阶段环环相扣共同构成了一个动态自适应的内存调度系统。3.1 第一阶段运行时状态感知这个阶段的目标是收集调度决策所需的基础数据。我们引入了两个时间概念量子Quantum一个固定的、较短的系统时间片例如10万tick时钟周期。这是调度策略做出一次决策和执行的基本时间单位。周期Cycle由多个量子例如4个组成一个更大的时间窗口用于进行历史趋势分析。在每个量子内内存控制器中的PPBP逻辑需要实时统计三个关键指标numREQ_CPU当前请求缓冲区中来自CPU核心的请求数量。numREQ_GPU当前请求缓冲区中来自GPU计算单元CU的请求数量。GPUThread_quantum在当前量子内请求缓冲区中出现的不同的GPU线程ID的数量。这代表了当前时刻正在发起内存访问的GPU线程规模。注意这里统计的是“不同的线程ID”而不是请求总数。因为一个GPU线程可能发出多个请求统计唯一ID更能反映并行访问的广度这对于评估延迟容忍度至关重要。在一个周期结束时我们会累计这个周期内出现过的所有不同的GPU线程ID得到GPUThread_cycle。这个值用于预测GPU的整体活跃规模。3.2 第二阶段GPU延迟容忍度预测与优先级计算这是PPBP算法的“大脑”。我们利用第一阶段感知到的数据来动态评估GPU的“耐心”有多大。延迟容忍度计算 GPU的延迟容忍度LatencyTolerance定义为预测的总活跃线程数与当前正在访问内存的线程数的比值LatencyTolerance GPUThread_cycle / GPUThread_quantum这个公式的直观理解是如果GPU有大量线程GPUThread_cycle大但其中只有很少一部分在等待内存GPUThread_quantum小说明GPU有很多其他就绪线程可以切换执行从而很好地隐藏内存访问延迟即延迟容忍度高。反之如果大部分线程都在等内存GPUThread_quantum接近GPUThread_cycle那么GPU就“等不起”了延迟容忍度低。GPU请求优先级/批处理比例计算 接下来我们综合当前请求负载和GPU的“耐心”计算出一个用于指导批处理的GPU优先级系数GPU_PriorityGPU_Priority G * [numREQ_GPU / (numREQ_CPU numREQ_GPU)] * [1 (1 / LatencyTolerance)]其中G是一个基础权重系数经实验设置为0.5。这个公式决定了下一个量子时间如何分配numREQ_GPU / (numREQ_CPU numREQ_GPU)反映了当前时刻GPU请求的紧迫性。GPU请求占比越高其获得服务时间的权重自然越大。1 (1 / LatencyTolerance)这是基于预测的调节因子。当GPU延迟容忍度低LatencyTolerance小时1 / LatencyTolerance值变大从而提高GPU优先级避免因其“等不及”而拖累整体进度。当GPU延迟容忍度高时这个因子接近1优先级主要取决于请求比例。最终计算出的GPU_Priority是一个介于0到1之间的值实际计算中会限制在此范围它直接代表了下一个量子时间内分配给处理GPU请求批次的时间比例。那么分配给CPU请求批次的时间比例就是1 - GPU_Priority。3.3 第三阶段基于FRFCFS的批处理调度这是PPBP的“执行手臂”。决策做出后调度器进入批处理执行模式如果当前决策是处理CPU批次那么在接下来的Quantum * (1 - GPU_Priority)时间内调度器只从请求缓冲区中选取CPU请求并采用标准的FRFCFS策略优先服务行命中请求其次服务最早的请求来处理它们。GPU请求在此期间被暂时搁置。当CPU批次时间用完或CPU请求被清空则切换到GPU批次在Quantum * GPU_Priority时间内只处理GPU请求。一个量子时间结束后流程回到第一阶段重新感知状态开始新一轮的预测和调度。这种批处理的核心好处减少行缓冲冲突连续处理同一类型CPU或GPU的请求更有可能访问相同或相邻的内存行从而大幅提高行缓冲命中率这是提升内存带宽利用率的关键。降低仲裁开销调度器无需在每个周期都在CPU和GPU请求之间做选择降低了决策频率和硬件复杂度。保护延迟敏感型请求通过动态调整批次比例可以在GPU“有耐心”的时候给CPU更长的连续服务时间显著改善CPU应用的性能。4. 硬件实现与开销分析为何PPBP更“实用”一个调度策略能否从论文走向芯片硬件实现复杂度是决定性因素。PPBP在这方面做了大量精简。4.1 所需的硬件状态与复杂的、需要监控GPU核心流水线的方案相比PPBP所有需要的信息都来自内存控制器内部仅需增加少量寄存器和一个计时器组件描述/用途额外比特数估算numREQ_cpu寄存器统计请求缓冲区中CPU请求数log₂(最大请求数)约6位numREQ_gpu寄存器统计请求缓冲区中GPU请求数log₂(最大请求数)约12位GPUThread_cycle寄存器记录一个周期内出现过的GPU线程ID数量log₂(最大线程数)约8位GPUThread_quantum寄存器记录当前量子内出现的不同GPU线程ID数log₂(最大线程数)约8位量子时间计数器计量量子时间到期触发更新取决于量子长度约20-30位总计PPBP所需的额外硬件存储开销大约在54到64比特之间连10个字节都不到这对于现代内存控制器来说几乎是微不足道的。4.2 执行流程与开销每个量子内对每个进入请求缓冲区的请求根据其源CPU/GPU和线程ID仅GPU更新对应的计数器和线程ID记录集合。这需要简单的比较和递增逻辑。量子结束时进行简单的算术运算除法、乘法来更新GPUThread_cycle、计算LatencyTolerance和GPU_Priority。这些计算可以通过一个小型状态机或微码实现。调度执行在批处理阶段直接使用现有的FRFCFS调度器逻辑只是将其输入限定为CPU或GPU的请求子集。这部分没有引入任何新的调度逻辑开销。由此可见PPBP的硬件实现极其轻量主要增加的是计数和定时逻辑复杂的预测和决策被简化为周期性的轻量级计算。这使其非常易于在真实的硬件设计中集成。5. 实验评估与性能分析PPBP表现如何我们基于gem5模拟器构建了一个包含8个CPU核心和16个GPU计算单元CU的异构系统模型并选取了PARSEC 3.0中的12个CPU基准测试程序和gem5-resources中的12个GPU基准测试程序进行混合负载测试。5.1 对比算法与评估指标我们将PPBP与以下算法进行对比FRFCFS作为基线代表当前许多系统的现状。FRFCFS-CapFRFCFS的改进版限制一个应用能连续发起的行命中请求数量以防止单一应用霸占带宽。BLISS一种为同构多核CPU设计的高性能调度算法能动态将应用分为“被干扰”和“未干扰”两类并优先调度前者。我们使用两个核心指标加权加速比Weighted Speedup衡量系统吞吐量。值大于1表示性能提升。平均减速比Average Slowdown衡量应用间相互干扰的程度。值越大表示干扰越严重。5.2 性能提升结果在运行4个CPU和4个GPU基准测试的混合负载下PPBP取得了显著效果CPU性能如图6所示与基线FRFCFS相比PPBP平均提升了8.53%的CPU性能最大提升达到14.64%。即使与同构优化算法BLISS相比PPBP仍有约5%的性能优势。系统干扰如图8所示在应对CPU-GPU间干扰方面PPBP的表现明显优于其他算法。随着并发工作负载数量的增加其优势愈加明显。相比FRFCFSPPBP将CPU-GPU间的相互干扰平均降低了10.38%。GPU性能PPBP的设计目标是优先保障CPU性能不受损同时尽量不影响GPU。实验结果表明PPBP能够基本保持GPU性能与基线持平或仅有微小波动实现了设计目标。5.3 关键参数敏感性分析任何策略都有其关键参数PPBP的核心参数是量子大小Quantum Size和GPU基础优先级系数G’。我们对它们进行了敏感性分析量子大小图9量子大小决定了批处理的“粒度”。过小如1e3 ticks批处理效果不明显退化为类似FRFCFS的频繁交错调度。过大如1e7 ticksCPU或GPU请求批次等待时间过长反而增加尾延迟损害性能。最佳点实验发现量子大小在1e5 ticks左右时能提高CPU行缓冲命中率和控制单一批次等待时间之间取得最佳平衡CPU性能达到峰值。GPU基础优先级系数G’图10这个系数决定了GPU的“基础权重”。过小如0.3过度偏向CPUGPU请求等待时间过长GPU性能下降明显。过大如0.7过度偏向GPUCPU性能改善有限。最佳点系数在0.5时能在CPU性能提升和GPU性能保持之间取得一个很好的平衡。在0.3-0.55的范围内CPU性能变化平缓说明PPBP对参数有一定的鲁棒性。5.4 优势与局限性总结PPBP的优势显著的CPU性能提升通过批处理隔离干扰有效提升了延迟敏感的CPU应用性能。低硬件复杂度与高可实现性所有逻辑位于内存控制器无需修改CPU/GPU核心硬件开销极小。良好的可扩展性其复杂度不随核心数或应用数增加而显著增加适合大规模异构系统。对GPU性能友好在优化CPU的同时基本保持了GPU的性能不受损失。当前的局限性及未来方向GPU内部干扰PPBP目前主要处理CPU与GPU之间的干扰并未显式处理不同GPU核心之间的内存访问冲突。在GPU负载极高时这可能成为瓶颈。未来的工作可以将批处理的思想扩展到GPU内部对不同GPU核心的请求进行更细粒度的调度。工作负载感知当前策略对应用特性如内存密集型、计算密集型的区分不够。可以结合PC程序计数器或地址流模式识别实现更智能的、基于工作负载特征的动态优先级调整。6. 实操启示与工程化思考从研究到落地PPBP策略给我们带来了一些更广泛的工程启示对于架构师与芯片设计者“外部视角”足够有效很多时候我们不需要为了获取完美信息而设计极其复杂的监控电路。像PPBP这样利用系统层级已有的、易于获取的信号如请求缓冲区状态通过巧妙的算法进行推断往往能以很低的成本解决大部分问题。这是一种性价比极高的设计哲学。批处理是应对“洪流”的有效手段在面对像GPU内存请求这样具有爆发性、高带宽需求的任务时与其在细粒度上艰难地仲裁不如在宏观上划定时间片进行“分时复用”。这种思路在计算机体系结构中广泛应用如DRAM的突发传输、网络中的流量整形等。对于软件开发与优化者理解底层内存调度行为当你在异构系统上开发高性能应用时如果发现性能不符合预期特别是CPU性能不佳需要意识到可能是内存资源竞争导致的。尝试调整任务粒度、并发度或者使用异步传输、锁页内存等技术都有可能改变内存访问模式从而更好地适配底层调度器。基准测试的重要性如我们的实验所示不同工作负载混合CPU密集型 vs GPU密集型高访存 vs 低访存对系统性能影响巨大。进行充分的、代表真实场景的混合负载测试是评估和优化系统性能不可或缺的一环。对于系统调优者参数化设计的重要性PPBP中的量子大小和优先级系数都是可调的。在一个真实的系统中这些参数可能需要根据具体的工艺、频率、内存类型以及典型工作负载进行微调。提供一个可配置的接口能让系统在不同场景下达到更优的性能。PPBP策略为我们展示了一条清晰的路径通过轻量级的感知、合理的预测和简单的批处理规则就能显著缓解异构计算中最棘手的内存竞争问题。它平衡了性能、公平性和实现复杂度为下一代高效能异构SoC的内存子系统设计提供了一个务实而有效的参考方案。随着异构计算向更广泛、更深入的领域渗透这类智能、低开销的资源管理策略将变得愈发关键。