2

来自另一家公司的一些非常有经验的程序员告诉我一些针对特定 CPU 的低级代码优化技巧,包括流水线优化,这意味着以特殊顺序排列代码(显然是内联汇编),使其更适合流水线对于目标硬件。

由于存在乱序和投机执行,我只是想知道做这种低级的事情有什么意义吗?我们主要从事高性能计算,因此我们可以真正专注于一种非常特定的 CPU 类型来进行优化,但我只是不知道进行这种特定的优化是否有任何意义,任何人都有这里的经验,从哪里开始? 有这种优化的代码示例吗?非常感谢!

4

3 回答 3

6

我首先会说编译器通常会充分优化代码(即足够好),只要您的高级代码和算法得到优化,您就不必担心这一点。一般来说,只有当您有确凿的证据表明存在可以量化和追踪的实际性能问题时,才应该进行手动优化。

现在,话虽如此,总是有可能改进事情——有时是一点点,有时是很多。

如果您在高性能计算游戏中,那么这种优化可能是有意义的。有各种各样的“技巧”可以做到,但最好留给真正的专家,而不是胆小的人。

如果您真的想了解有关此主题的更多信息,最好从阅读Agner Fog 的网站开始。

于 2013-02-02T00:38:03.277 回答
3

管道优化将提高您的程序性能:

分支和跳转可能会迫使您的处理器重新加载指令流水线,这需要一些时间。这段时间可以专门用于数据处理指令。

流水线优化的一些平台无关方法:

  1. 减少分支机构数量。
  2. 使用布尔算术
  3. 设置代码以允许有条件地执行指令。
  4. 展开循环。
  5. 使循环具有短内容(无需加载即可放入处理器的缓存中)。

编辑 1:其他优化

  1. 通过消除功能和要求来减少代码。
  2. 审查和优化设计。
  3. 审查实施以获得更有效的实施。
  4. 仅当所有其他优化都没有提供很少的性能改进时才恢复为汇编语言;仅优化 80% 时间执行的代码;通过分析找出。

编辑 2:数据优化

您还可以通过组织数据来提高性能。在网上搜索“数据驱动设计”或“优化性能数据”。

一种想法是最常用的数据应该靠近在一起并最终适合处理器的数据缓存。这将降低处理器必须重新加载其数据缓存的频率。

另一个优化是:加载数据(到寄存器中),对数据进行操作,然后将所有数据写回内存。这里的想法是在处理器处理数据(或寄存器)之前触发处理器的数据缓存加载电路。

如果可以的话,组织数据以适应处理器缓存的一个“行”。顺序位置比随机访问位置需要更少的时间。

于 2013-02-02T00:32:31.717 回答
1

总有一些事情“帮助”与“阻碍”管道中的执行,但对于大多数不是高度专业化的通用代码,我希望编译代码的性能与你能得到的最好的一样好没有针对每种处理器型号的高度专业化的代码。如果您有一个受控系统,您的所有机器都使用相同(或少数类似)处理器型号,并且您知道 99% 的时间都花在了这个特定功能上,那么优化该特定功能以提高效率。

在您的情况下,它是 HPC,手写一些低级代码(例如矩阵乘法)以针对您正在运行的处理器进行优化可能是有益的。但是,这确实需要对处理器有一些合理的了解,因此您需要研究该处理器型号的优化指南,如果可以的话,请与以前使用过该处理器的人交谈。

您要查看的一些内容是“注册以注册依赖项”-您需要 c = a + b 的结果来计算 x = c + d -因此您尝试将这些与其他一些有用的工作分开,例如x 的计算不会被 c = a + b 计算所阻碍。

缓存预取和通常关心缓存的使用方式也是一件有用的事情 - 当您存储不会再次使用的生成的 1MB 数组时,不要将有用的缓存数据踢出,因为您需要 100 条指令几秒钟可能值得大量的处理器时间。

当编译器决定在自己的优化中对其进行洗牌时,很难(呃)控制这些东西,所以手写汇编器几乎是唯一的方法。

于 2013-02-02T00:32:38.950 回答