![How Can We Intentionally Deoptimize a Program to Expose Intel Sandybridge Pipeline Bottlenecks?](https://img.php.cn/upload/article/000/000/000/173374227378350.jpg)
对 Intel Sandybridge 系列 CPU 中的流水线程序进行去优化
问题:
任务是在给定程序中引入低效率,以减慢其执行速度。该程序是使用高斯随机数的蒙特卡洛模拟,重点是利用 Intel Sandybridge 系列 CPU 的管道结构。
解决方案:
导致管道效率低下危险:
-
将原子操作与存储加载栅栏一起使用:对共享变量的重复原子操作会创建内存依赖性,从而导致管道停顿。此外,存储加载栅栏会强制内存操作的串行执行。
-
创建错误共享:确保多个线程访问不同缓存行中的相邻内存位置,从而导致缓存组冲突和失效。
-
使用不规则的内存访问模式:避免顺序内存访问以防止高效的预取和缓存利用。例如,以不连续的顺序访问元素或使用链表代替数组。
弱化循环级并行性:
-
序列化循环迭代:使用锁或原子增量等同步机制来确保只有一次线程一次执行每个循环迭代。
-
引入不可预测的分支:包含分支预测器难以预测的分支,当采取错误的路径时会导致错误预测和管道刷新。
-
使用低效运算:用较慢的替代方案替换高效的算术运算,例如除法而不是乘法,或平方用根代替乘法,用常数乘法代替对数和指数函数。
利用微架构功能:
-
导致不必要的寄存器溢出和填充: 使用许多局部变量和大型数据结构,强制溢出和填充操作
-
使用低效指令:利用会导致严重停顿或降低指令级并行性的指令,例如未对齐的内存访问或 32 位模式下的 16 位操作。
-
争夺缓存资源:通过访问多个数组或数据结构造成过多的缓存未命中同时,使用非连续内存访问模式,或使用 CLFLUSH 等指令显式使缓存行无效。
编译器优化避免:
-
使用内联汇编:通过使用内联汇编手动控制指令生成来绕过编译器优化,并避免缓存友好的代码转换。
-
使用未定义的行为: 执行可能导致意外行为或生成低效代码的操作,例如非指针类型或未初始化内存上的指针算术
-
强制不必要的重新编译:以需要重新编译的方式更改代码,例如添加注释或修改宏,以使缓存的代码路径无效并降低编译器优化的有效性。
结论:
作者将这些低效率的问题纳入程序中,可以显着降低其执行速度,并凸显优化现代管道架构代码的重要性。然而,值得注意的是,这些技术并不是为了在实际应用中实际使用,而只是为了说明不良优化对性能的潜在影响。
以上是我们如何有意地对程序进行去优化以暴露 Intel Sandybridge 管道瓶颈?的详细内容。更多信息请关注PHP中文网其他相关文章!