【问题标题】:Instruction Level Profiling: The Meaning of the Instruction Pointer?指令级分析:指令指针的含义?
【发布时间】:2013-06-05 07:11:56
【问题描述】:

在汇编指令级别分析代码时,鉴于现代 CPU 不串行或按顺序执行指令,指令指针的位置真正意味着什么?例如,假设以下 x64 汇编代码:

mov RAX, [RBX];         // Assume a cache miss here.
mov RSI, [RBX + RCX];   // Another cache miss.             
xor R8, R8;        
add RDX, RAX;           // Dependent on the load into RAX.
add RDI, RSI;           // Dependent on the load into RSI.

指令指针将大部分时间花在哪条指令上?我可以为他们想出好的论据:

  • mov RAX, [RBX] 可能需要 100 多个周期,因为它是缓存未命中。
  • mov RSI, [RBX + RCX] 也需要 100 个周期,但可能与前一条指令并行执行。指令指针位于其中一个或另一个上意味着什么?
  • xor R8, R8 可能会乱序执行并在内存加载完成之前完成,但指令指针可能会一直停留在此处,直到所有先前的指令也完成为止。
  • add RDX, RAX 会产生流水线停顿,因为它是在慢速缓存未命中加载后实际使用 RAX 值的指令。
  • add RDI, RSI 也会停止,因为它依赖于 RSI 的负载。

【问题讨论】:

    标签: performance assembly profiling x86-64 low-level


    【解决方案1】:

    这是一个很好的问题,但在the kind of performance tuning I do 中,这并不重要。 这并不重要,因为您正在寻找的是速度错误。 这些是代码正在做的事情,需要花费时钟时间,并且可以做得更好或根本不做。示例:
    - 花 I/O 时间在 DLL 中查找实际上不需要查找的资源。
    - 花时间在内存分配例程中创建和释放可以简单地重复使用的对象。
    - 重新计算函数中可以记忆的东西。
    ...这只是我脑海中的一些想法

    你最大的敌人是一种自我祝贺的倾向,说“我不会有意识地写任何错误。我为什么要写?”当然,您知道这就是您测试软件的原因。但是对于速度错误也是如此,如果你不知道如何找到那些你假设没有,这是一种说法“我的代码没有可能的加速,除了可能profiler 可以告诉我如何剃掉几个周期。”

    在我半个世纪的经验中,没有代码在最初编写时不包含速度错误。更重要的是,还有一个巨大的乘数效应,你消除的每一个速度问题都会使剩下的问题更加明显。作为一个人为的例子,假设 bug A 占时钟时间的 90%,而 bug B 占 9%。如果你只修复 B,那很重要 - 代码快 11%。如果你只修复 A,那很好——它快 10 倍。但是,如果您同时解决这两个问题,那就太好了——速度提高了 100 倍。固定 A 使 B 变大。

    因此,您在性能调整中最需要的是找出速度问题,不要错过任何问题。完成所有这些后,您就可以开始进行周期调整了。

    【讨论】:

      【解决方案2】:

      CPU 保持一种虚构,即只有架构寄存器(RAX、RBX 等),并且有一个特定的指令指针 (IP)。程序员和编译器以这种虚构为目标。

      然而,正如您所指出的,现代 CPU 不会串行或按顺序执行。直到程序员/用户请求 IP,就像量子物理学一样,IP 是一波正在执行的指令;所有这些都是为了让处理器可以尽可能快地运行程序。当您请求当前 IP(例如,通过调试器断点或分析器中断)时,处理器必须重新创建您期望的虚构,以便它折叠此波形(所有“飞行中”指令),将寄存器值收集回架构名称,并为执行调试器例程等构建上下文。

      在此上下文中,有一个 IP 指示处理器应恢复执行的指令。在乱序执行期间,该指令是尚未完成的最旧指令,即使在中断发生时处理器可能正在获取远远超过该时间点的指令。

      例如,也许中断指示mov RSI, [RBX + RCX];为IP,但xor已经执行完毕;但是,当处理器在中断后恢复执行时,它将重新执行异或。

      【讨论】:

      • 您能解释一下硬件性能监控计数器在这种情况下是如何运作的吗?例如。 Linux 具有perf 子系统,可提供基于 PMC 的统计分析。内核是否只是生成一个高频中断,然后根据您的非常好的类比,它会折叠 IP 波​​函数并读出 PMC,然后将 PMC 的当前值分配给当前找到的 IP(在波之后功能崩溃)?然后重置 PMC 并从中断中恢复?
      • 那么当上下文切换发生时会发生同样的事情吗?操作系统将存储尚未完成的最旧指令的上下文,并且必须重新执行乱序执行的指令?
      • 是的。上下文切换(通常)依赖于定时器中断。在任何中断时,硬件都会为 OS 提供下一条指令的 IP,以便 OS 可以在该指令处恢复进程的执行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      • 2011-12-29
      • 1970-01-01
      相关资源
      最近更新 更多