【发布时间】:2014-01-23 04:52:56
【问题描述】:
我正在我的大学学习并行计算课程,显然我们需要了解程序员级别的架构。谁能说出开发多核处理器的动机是什么?为什么多线程处理器不够用?为什么我们需要将管道分布在多个核心上,而不是将它们放在一个大核心上?
【问题讨论】:
标签: multicore computer-architecture hyperthreading
我正在我的大学学习并行计算课程,显然我们需要了解程序员级别的架构。谁能说出开发多核处理器的动机是什么?为什么多线程处理器不够用?为什么我们需要将管道分布在多个核心上,而不是将它们放在一个大核心上?
【问题讨论】:
标签: multicore computer-architecture hyperthreading
随着 CPU 变得越来越小,速度越来越快,它们接近了几个物理极限,这使得在当前路径上继续运行的成本更高:
这就是 CPU 制造商转向多核的原因。理论上,四个核心的处理能力是一个核心的四倍。一些应用程序可以实现这一点,但大多数不会。随着时间的推移——也许——越来越多的应用程序可以更好地利用多核。
在任何时候,构成 CPU 的大多数组件都没有被使用,理论上可用于处理。这就是超线程存在的理由。两个不同的执行线程可以并行运行,只要它们不需要同时访问同一个组件。但他们经常这样做。然后一个必须停下来等待另一个。
另辟蹊径:可以在芯片上实现的必要功能将始终比在其他地方实现更快的执行速度。外部存储器将始终以 CPU 内部速度的一小部分执行。 80286在CPU芯片上集成了内存保护和虚拟内存。这使得它比在芯片外实现功能的竞争设计要快得多。尽管 80386 芯片组的变体实现了片外高速缓存,但 80486 具有片上 L1 高速缓存。然后是片上 2 级 (L2) 和后来的 L3 缓存。 Pentium 有一个宽两倍的外部存储器接口,可以在同一时间跨度内读取两倍的数据。后来出现了两个或更多的外部存储器接口。后来,外部存储器的控制器被移到芯片上,以减少对正常操作的干扰。每次访问时,内存芯片可以提供两倍 (DDR)、四倍 (DDR2) 或八倍 (DDR3) 的数据。 DDR4 正在开发中。可以看出,实际 CPU 和外部存储器之间的接口变得越来越复杂,才能勉强获得那一点额外的性能。实施的解决方案基于最适合通用情况的常见访问场景,以便标准软件运行得更快一点。专业软件试图更有效地使用界面,并可以实现惊人的性能。大多数其他软件永远不会接近。相当多的混乱应用程序甚至会超出正常的访问模式并变得更慢,因为它们与界面不符。
如果您退后一步,您会意识到“最佳”解决方案是在 CPU 和外部存储器之间建立一条直接的、最简单的路径。曾经有一台标准计算机可以做到这一点 - 基于 80386 的 Compaq Deskpro 386/20 - 它使用静态 RAM (SRAM) 而不是现在每个人都使用的动态 RAM (DRAM)(因为它的价格要便宜得多内存单位)。 SRAM 能够与 CPU 保持同步,而 CPU 在多周期指令期间实际上会更慢。
我的意思是说,许多因素会影响整体硬件性能,因此说“CPU 性能”可能意味着很多事情。他们都一起工作,并经常合作以取得更好的业绩。有时他们会做相反的事情。
当同时访问相同的资源时,超线程会发生冲突。此类资源不限于 CPU 中的功能组件。超线程共享相同的缓存和内存接口,也会在那里发生冲突。非超线程多核也会发生冲突,但这会发生在它们访问公共资源时,这通常意味着 L3 缓存和内存接口。只要它们停留在专属于它们的资源(核心、L1 和 L2)内,它们就可以不间断地运行。
主存储器可以最大速率传送数据。在一个标准的、优化不佳的应用程序中,它通常以 100% 的速率工作。如果可以将 100% 平均分配给可用的 n 个内核,则最佳状态是。
设计良好的硬件解决方案将比其他解决方案更快地处理。通过将硬件设计考虑在内,旨在提高运行效率的软件将胜过普通软件。
一个有点复杂的答案,但这是一个复杂的主题:-)
【讨论】:
多线程处理器实际上不能同时执行代码。他们唯一要做的就是虚拟化处理器,使操作系统看起来像两个物理内核,这有一点速度优势。
没有超线程的单核处理器有时可能会浪费时间等待指令完成,因为它需要获取数据,或者它有缓存未命中或者可能是错误的分支预测。虽然乱序执行可以解决其中的一些问题,但添加另一个线程可以接管并使用 CPU 资源一段时间,而另一个线程被阻塞可以提高性能。
但是,这个带有超线程的单核仍然只有一个 FPU、一个 ALU、一个控制单元、一个内存接口等。由于这个限制,真正的并发线程执行需要复制这些组件。复制内核并指定它们之间的接口比尝试平衡多个 ALU 或 FPU 的设计要简单得多,单个内核中有多个线程。
【讨论】:
增加单个内核的宽度会在硅面积和功耗方面产生几何成本。
制作大小合理的内核的多个副本具有线性成本(+ 互连/一致性的开销很小)。
制造一个超宽 CPU 只是为了用 SMT(又名超线程)将它切碎是很疯狂的。如果您需要出色的单线程性能,您会这样做,并且可以以某种方式冷却芯片,使其以接近更窄设计可以管理的时钟速度运行。 (你不能。)
大多数代码中没有足够的指令级并行性来提供足够大的改进来证明更广泛的设计是合理的。您在 IPC 中获得的任何东西(每个时钟的 insns)都会在时钟速度上有所损失,因为您无法在不过热的情况下快速运行它。
例如,20 年来,英特尔已从 3 宽问题宽度(PPro 中的原始 P6 到 Pentium-M)发展到 4 宽问题宽度(Core2 到 Skylake)。 x86 难以解码,但带有 uop-cache 的 SnB 系列设计很容易拥有比解码器吞吐量更宽的 OOO 管道。
增长更多的是执行端口的数量,以及每个端口上执行单元的数量。在最近的英特尔设计中,相同的指令可以在不同的数据上并行运行。例如Haswell 和更高版本可以在每个时钟执行两个 FP 乘法。 IvB 和更早的版本只有一个 FP mul 每个时钟的吞吐量,因为只有一个 FP mul 执行单元(在 port1 上)。
较旧的设计(如 PIII)只有两个 ALU 执行端口,因此他们可以管理的每个时钟的三个指令中的一个必须是内存操作(加载或存储)。 Haswell 有四个 ALU 端口(其中三个可以处理向量指令)。因此,无论指令的组合如何,最新的 CPU 都很有可能并行执行很多任务。
拥有大量芯片区域但很多时候不做任何事情的“低效率”不是问题。真正的限制因素是功率,而不是死区。这就是为什么现代 CPU 可以拥有如此多的无法一次使用的执行能力。
请注意,如果超线程可以使 HT 在内核之间共享的执行资源饱和,那么它实际上会减慢您的代码速度。或者更糟糕的是,如果来自竞争性共享 L1/L2 缓存的额外缓存压力导致每个线程中出现更多的缓存未命中。
当一个或两个线程在给自己一个完整的内核时实现低指令/时钟 (IPC) 时,HT 是一个巨大的胜利。隐藏内存延迟的两个乱序窗口很好,对于分支错误预测非常有用。
对于在不同执行单元上出现瓶颈的两个线程来说,这是一个小小的胜利。 (例如,端口 5 上的 shuffle 单元与端口 0/1 上的 add/mul)。
【讨论】: