【问题标题】:New instruction sets in CPUCPU 中的新指令集
【发布时间】:2011-02-01 13:45:33
【问题描述】:

每一代新的 CPU 都会引入一些新指令集,即 MMX、3DNOW、SSE 等。

我有几个关于它们的一般性问题:

  1. 如果某些程序使用例如 SSE 指令,它可以在不支持 SSE 的 CPU 上运行吗?
  2. 如果是,是否意味着这些指令将被更改为更多更简单的指令?
  3. 如果不是,是否意味着此类新指令的真正性能影响将在几年后大多数 CPU 将支持此类技术(因此不会出现任何不兼容性)?
  4. 当我编译一个带有优化的 C++ 程序时,这是否意味着它会使用这些新指令? (我知道这取决于许多因素,尤其是代码,但我想要一些一般性的答案)。还是它们主要用于用 asm 编写的程序?

【问题讨论】:

  • 据我所知,过去 3-4 年制造的任何处理器,无论是 Intel 还是 AMD,都至少支持 SSE2。您可能只是假设他们在那里,具体取决于您的目标受众。
  • @Blindy:总的来说,这不是一个好主意。如果您的程序不是一个巨大的资源消耗者,那么在十年前的硬件上运行应该不是问题。也就是说,如果您的程序针对 64 位操作系统,或者仅在 Windows 8 或更高版本上运行,那么您可以安全地使用 SSE2 及更低版本(所有 x86-64 处理器都至少包含 SSE2 支持,并且 Windows 8 强制要求 SSE2 支持,即使对于32 位版本的操作系统)。

标签: x86 cpu simd instruction-set


【解决方案1】:

包含新指令的可执行文件只能在支持这些新指令的 CPU 上执行。您可以将编译器配置为针对特定 CPU 进行编译。

【讨论】:

  • 只有当这些指令真正被执行时。如果它们从未被执行(例如,因为它们在检查当前 CPU 是否支持它们的条件跳转后面),那么就没有问题。 IOW:当且仅当 CPU 实际尝试执行一个操作码时,CPU 才会捕获非法操作码。
【解决方案2】:
  1. 是和否:CPU 将认为它们无效,但如果程序检查 CPU 是否支持这些指令,则它可以回退到不使用这些指令的版本,从而允许程序运行.
  2. 程序必须使用更“基本”的指令提供替代实现,并知道何时使用哪个指令。
  3. 由于程序可以检查 CPU,因此可以立即获得好处,但是当然,如​​果您的用户使用不支持这些指令的 CPU,他们将看不到任何好处。
  4. 这完全取决于编译器和优化器。一些指令集可能被认为足够老,编译器将始终使用它们,除非你告诉它不要这样做,而另一些则相反:你必须告诉编译器使用它们。它是否也会自动创建回退也取决于编译器。

【讨论】:

    【解决方案3】:

    MMX 自 1996 年以来一直存在,SSE 于 1999 年问世,SSE2 于 2001 年与 Pentium 4 一起首次亮相。我认为可以肯定地假设您将使用的任何 CPU 都具有 MMX 和 SSE,并且可能还有 SSE2。 3DNOW 我认为只有 AMD,所以不要指望这些指令可用。

    【讨论】:

      【解决方案4】:

      为了详细说明 Michael Madsen 对问题 4 的回答,GCC 默认为 i386 处理器生成代码。它提供了一个名为-march(也称为-mcpu)的标志,用于确定编译器将发出哪种指令。微软的cl.exe 提供/arch:/Gx 标志用于相同目的。

      该标志还会影响指令的排序方式,因为不同的 CPU 执行一段给定代码的速度可能相对较慢或较快,具体取决于指令出现的顺序。

      我不知道有任何静态编译器会创建自动功能集后备代码。通常这必须由程序员明确地完成。但好消息是,程序员不一定是你;例如,liboil 库(优化内循环)将在运行时根据运行它的机器选择要运行的最佳代码。

      【讨论】:

      • 大多数发行版配置 gcc,因此它的 32 位代码生成默认使用 Pentium Pro 作为指令集基线,而不是 i386(cmov 但不是 MMX 或 SSE)。您还可以构建 gcc,以便默认的 32 位代码生成启用 SSE2。 x86-64 (-m64) 模式使用第一代 K8 作为基线,因此使用 SSE2 而不是 cmpxchg16b (-mcx16),这是 x86-64 之后的首批扩展之一。
      • 顺便说一句,您可以将 -mtune=haswell-march=nehalem 分开设置,因此您的代码将在 Nehalem 或更新版本上运行,但指令选择和排序针对较新的 CPU 进行了优化。
      【解决方案5】:
      1. 如果某些程序使用例如 SSE 指令,它可以在不支持 SSE 的 CPU 上运行吗?

      没有。但一般来说,这通常会产生一个陷阱或异常,如果需要,陷阱/中断处理程序可以处理它。

      例如,很久以前的软件通常包含 x87 的代码。如果有 x87 协处理器,该指令在硬件中可以正常运行,但如果计算机没有 x87 协处理器,则会产生一个陷阱,之后该指令将在软件中处理并正常返回结果。见What is the protocol for x87 floating point emulation in MS-DOS?

      Hackintosh 的第一个版本也使用它在不支持此指令集的 CPU 上模拟 SSE2。当然性能很糟糕,但它会运行。

      1. 如果不是,这是否意味着此类新指令的真正性能影响将在几年后大多数 CPU 将支持此类技术(因此不会出现任何不兼容性)?

      是的。但几年后,也许软件需要更新,对吧?对于关键性能软件,可能需要重写以利用新指令集。对于其他一些人来说,性能的提升可能并不明显

      1. 当我编译一个带有优化的 C++ 程序时,这是否意味着它会使用这些新指令? (我知道这取决于很多因素,尤其是代码,但我想要一些一般性的答案)还是它们主要保留给用 asm 编写的程序?

      取决于编译器和您在编译时传递给它的选项。

      现代编译器支持,因此它们将支持detect common idioms and optimize it。您只需重新编译 即可利用新指令集。但对于复杂的情况,您仍然需要手动优化使用 SIMD 内在函数

      如果您使用外部库,当库更新以支持新指令集时,您将自动获得速度提升,即使您对程序不做任何事情也是如此 p>

      【讨论】:

      • 澄清一下,现在在中断处理程序中进行 SSE 仿真需要内核补丁。用户空间软件不能挂钩 Linux 或 Windows 中的中断处理程序。或者也许你可以在用户空间的 SIGILL 处理程序中做到这一点?当然,如果需要额外往返用户空间和返回,则速度会更慢。
      猜你喜欢
      • 2013-06-27
      • 2011-05-24
      • 1970-01-01
      • 2016-12-27
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      • 2012-10-08
      • 1970-01-01
      相关资源
      最近更新 更多