为什么需要针对相同架构的新处理器优化引擎?


39

新一代处理器发布后,大多数网站报告说,游戏引擎和程序需要针对新硬件进行优化。我不太明白为什么。处理器通常具有定义其使用哪种指令集的体系结构。如今我们都使用的是amd_x86_64。如果所有处理器都使用相同的体系结构,为什么需要更新任何程序或编译器?当然,在新处理器的管道中有一些功能可以优化机器代码的执行,但是如果不需要该体系结构,为什么还要更改机器代码本身呢?


评论不作进一步讨论;此对话已转移至聊天
乔什

14
“需要”是一个错误的措辞,比真实情况更重要的营销手段,例如Windows 需要支持某些新一代CPU(或者像Windows 7那样不需要,这在原则上可以完美地工作)可以使用Ryzen进行调整,除非使用的功率比必要的多3-4%)。这种调整仅是要尝试从CPU中挤出更多一点,使其接近最大值。实际上,由于不同的计划和使用一些新的指令,您可能会在非人为的示例中获得总计1-2%的收益。
戴蒙

2
仅仅是因为两个处理器可以执行相同的操作,并不意味着两个处理器都具有相同的性能……
Mehrdad

在Stack Overflow上看到我的一个相关问题:mtune实际如何工作?
Marc.2377 '12

Answers:


54

因为同一体系结构的不同可以具有不同的指令集

例如,Streaming SIMD Extensions可能是最著名的x86指令集,但是,尽管只有一种x86架构,但仍然存在SSE,SSE2,SSE3和SSE4。

这些代中的每一代都可以包括新指令,这些指令提供了执行某些操作的更快方法。与游戏相关的示例可能是点产品说明。

因此,如果游戏引擎是为上一代架构编译的,则它将不支持这些较新的指令。同样,可能有必要针对新指令优化引擎。例如,SSE4支持对结构数组数据起作用的点积指令。可以利用这些较新指令的优化方法是将数据布局更改为结构数组。


1
@Panzercrisis-谢谢您的编辑建议。需要明确的是:最初的问题不是关于您自己的代码,而是关于引擎代码,因此“优化自己的代码”不是一个好的编辑建议。但是,它确实强调了我需要澄清的一点,当我说“优化”时,我的意思是“优化引擎代码”,因此我进行了编辑以接受该内容。
Maximus Minimus

37

Maximus的回答是正确的,我只想再讲一个故事:

不管新引入的指令如何,硬件本身都会以需要更改编码方式的方式进行更改。

  • 高速缓存数量的增加或减少意味着您需要更少或更多地担心高速缓存优化/高速缓存失效问题。更多的高速缓存意味着对于较小的数据,您可以将精力集中在确保数据连续而不会出现性能问题上。较少的缓存意味着这可能是一个问题,而很少的缓存意味着对于某些大型数据结构而言,这将无关紧要。

  • 全新的缓存级别意味着您需要更多地考虑如何组织更大的数据集(L1,L2,L3与L4)。

  • 更多的内核意味着您需要考虑如何更好地处理多线程应用程序,以及在多进程环境中如何扩展应用程序。

  • 更快的时钟频率意味着您需要更多地考虑内存延迟,而不是将CPU计算速度视为系统的瓶颈。

  • 系统上FPU的数量可能不再与每个内核的整数ALU数量匹配(AMD具有这样的体系结构)。

  • 计算一个运算所需的时钟周期数已减少或增加。

  • 可用的寄存器数已更改。

所有这些都对程序产生了非常真实的性能影响,这些程序对具有相同ISA的以前硬件中的基础体系结构(无论是肯定的还是否定的)进行了假设。


“增加或减少高速缓存级别意味着您不必担心高速缓存一致性。”-几乎所有CPU都是高速缓存一致性的。您的意思是虚假分享吗?甚至比几乎任何CPU $线几乎总是64 B ...
Maciej Piechotka '17

1
Maciej只是接受有关缓存一致性的声明:)您可能是指“缓存优化”之类的。高速缓存一致性是指即使存在N个独立的高速缓存,系统也可以使软件对软件透明地保持一致的内存视图的能力。这与大小完全正交。TBH该声明并不是真正相关,但是您的答案(尤其是第5点和第6点)要比公认的IMO更好地解决了这个问题:)也许强调体系结构与u-architecture之间的区别将使其更加突出。
玛格丽特·布鲁姆

4
“就像乘法要花费比加法更多的时间,而在今天的现代intel和AMD CPUS上,它花费的时间是相同的。”并不是全部。在流水线架构中,您必须区分延迟(准备好结果时)和吞吐量(每个周期可以执行多少次)。现代英特尔处理器上的Int加法器的吞吐量为4,延迟为1。乘积的吞吐量为1,延迟为3(或4)。这些都是随每种体系结构而变化并且需要优化的事物。例如pdep,intel需要1个周期,而Ryzen需要6个周期,因此可能不想在Ryzen上使用它。
克里斯托夫(Christoph)

2
@Clearer我知道我们在这里谈论CPU,但是您从未为GPU编程吗?相同的代码在性能上产生了截然不同的结果,实际上常常迫使您不得不考虑CUDA中的硬件功能。这就是我的来历,在使用CUDA编写代码时,实际上需要考虑缓存大小(共享内存,托管L1缓存)。
opa

2
@Christoph是正确的。您链接的基准是针对阵列上的循环c[i] = a[i] OP b[i](即,每次操作2个负载和1个存储),因此由于计算强度非常低,因此时间由内存带宽决定。未显示阵列大小,因此IDK如果适合L1D。(gcc4.9 -Ofast很有可能会自动对这些循环进行矢量化处理,因此,您甚至都无法测量作为复杂整数代码一部分的常规标量运算的成本)。该页面的第一行很重要:有用的反馈表明,其中一些措施存在严重缺陷。正在进行重大更新
彼得·科德斯

2

甚至在诸如对新指令的支持等重大变化之外,微处理器制造商也在不断修改其设计以提高性能,并且每种新设计对于每种指令或技术可能具有不同的相对性能。也许您为Model X编写了一些经过仔细优化的无分支代码,但是Model Y的分支预测器得到了改进,从而减少了非分支版本代码的误预测损失(这也释放了寄存器供其他地方使用) 。也许Model Y支持某种高延迟指令的更大并行度,所以现在该指令的展开循环可以为您带来更好的吞吐量,而Model X上较短的序列则更好。

任何问题都可以通过多种方式解决,并且从优化的角度来看,每个程序都是权衡取舍和资源分配的连锁集合。即使这些资源的可用性或给定代码段的成本在这些资源方面进行了很小的更改,也会产生级联效应,从而使一个或另一个代码段具有显着的性能优势。即使升级的芯片拥有“更多的东西”,每件东西多少也可以平衡。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.