GPU被设计用来快速处理大量数据,配备了称为流处理器(SMs)和各种设施以确保数据流的稳定性。尽管具备这些能力,数据匮乏仍然可能发生,导致性能瓶颈。根据NVIDIA技术博客,最近的一项调查强调了指令缓存未命中对GPU性能的影响,特别是在基因组工作负载场景中。
识别问题
调查集中在使用Smith-Waterman算法的基因组应用程序上,该算法涉及将DNA样本与参考基因组进行对齐。当在NVIDIA H100 Hopper GPU上执行时,该应用程序最初表现出了令人鼓舞的性能。然而,NVIDIA Nsight Compute工具显示,流处理器有时面临数据匮乏问题,不是因为数据不足,而是因为指令缓存未命中。
由众多小问题组成的工作负载在流处理器之间造成了不均衡分布,导致一些流处理器处于空闲状态而其他流处理器继续处理。这种不平衡称为尾效应,当工作负载增加时尤为明显,导致显著的指令缓存未命中和性能降低。
解决尾效应
为了减轻尾效应,调查建议增加工作负载大小。然而,这种方法导致了意想不到的性能下降。NVIDIA Nsight Compute报告表明,主要问题是由于指令缓存未命中导致的warp停顿迅速增加。流处理器无法足够快地获取指令,导致延迟。
设计用来存储靠近流处理器已获取指令的指令缓存,被要求的指令数量随着工作负载大小的增加而感到不堪重负。这种现象发生的原因是warp(线程组)在执行过程中逐渐偏离,导致指令集多样化,使缓存难以容纳。
解决问题
解决此问题的关键在于减少整体指令占用,特别是通过调整代码中的循环展开。循环展开尽管有助于性能优化,但增加了指令数量和寄存器使用,可能加剧缓存压力。
调查尝试了内核中最外层两个循环的不同展开级别。发现最小的展开,特别是将第二级循环展开因子设为2而避免最高级循环展开,表现最佳。这种方法减少了指令缓存未命中并改善了warp占用,使性能在不同工作负载规模间达到平衡。
进一步分析NVIDIA Nsight Compute报告证实,减少代码中最热部分的指令内存占用显著缓解了指令缓存压力。这种优化方法特别针对大型工作负载,提升了总体GPU性能。
结论
指令缓存未命中可能严重影响GPU性能,特别是在具有大指令占用的工作负载中。通过尝试不同的编译器提示和循环展开策略,开发者可以实现优化后的代码性能,减少指令缓存压力并改善warp占用。
欲了解更多详细信息,请访问NVIDIA技术博客。
Image source: Shutterstock