【问题标题】:Does the branch predictor also include I/O instructions in its prediction?分支预测器是否也在其预测中包含 I/O 指令?
【发布时间】:2016-07-11 05:47:27
【问题描述】:

我目前正在编写一个 Intel 8042 驱动程序,并编写了两个循环来等待一些缓冲区准备好使用:

/* Waits until the Intel 8042's input buffer is empty, i.e., until the
 * controller has processed the input. */
i8042_waitin:
    pause
    in $i8042_STATUS, %al
    and $i8042_STAT_INEMPTY, %al
    jz i8042_waitin
    ret

/* Waits until the Intel 8042's output buffer is full, i.e., data to read is
 * available.
 * ATTENTION: this here is the polling variant but there is also a way with
 * interrupts! By setting bit 0 in the command byte you can enable an interrupt
 * to be fired when the output buffer is full. */
i8042_waitout:
    pause
    in $i8042_STATUS, %al
    and $i8042_STAT_OUTFULL, %al
    jz i8042_waitout
    ret

如您所见,我在循环中插入了pause 指令。我最近才知道它,自然想尝试一下。
由于%al 的内容是不可预测的,因为它是 I/O 读取,因此分支预测器将用循环指令填充管道:经过一些迭代后,它会注意到始终采用一个分支,类似于 the case here

如果分支预测器确实在其预测中包含 I/O 指令,则上述内容是正确的,我不确定。

那么分支预测器是否会使用 I/O 指令的结果进行自我调整,就像不可预测的内存读取一样?还是这里发生了其他事情?
pause 在这里有意义吗?

【问题讨论】:

    标签: performance loops assembly x86 pause


    【解决方案1】:

    分支预测器在预测中不包含任何其他指令。它只是根据分支指令本身和/或其先前的分支历史进行猜测。循环中的其他指令,PAUSE,IN 或 AND 对分支预测没有任何影响。

    answer you linked 中建议的 PAUSE 指令并不打算影响分支预测器。这是为了防止当该问题示例代码中的 CMP 指令访问的内存位置被另一个处理器写入时发生流水线停顿。 CMP 指令也不影响分支预测。

    Peter Cordes 提到,您可能会对 CPU 用于推测执行指令以试图保持其流水线充满的不同技术感到困惑。在您链接的问题中,推测执行最终会损害自旋锁的性能有两种不同的方式。两者都有一个共同的根,CPU 试图尽可能快地执行循环,但实际上影响自旋锁性能的是它退出循环的速度。只有循环最后一次迭代的速度很重要。

    自旋锁代码的推测执行问题的第一部分是分支预测器将很快假设分支总是被采用。在循环的最后一次迭代中会出现停顿,因为 CPU 将继续推测性地执行循环的另一次迭代。它必须把它扔掉,然后开始在循环外执行代码。但事实证明情况更糟,因为 CPU 会推测性地读取 CMP 指令中使用的内存位置。因为它访问正常的内存,推测性读取是无害的,它们没有副作用。 (这与您的 IN 指令不同,因为从设备读取的 I/O 可能会产生副作用。)这允许 CPU 推测性地执行循环的多次迭代。当另一个 CPU 更改内存位置时,这会使依赖于管道中推测读取的所有指令无效,因此执行自旋锁的 CPU 在从管道中清除它们时最终会停止。

    在您的代码中,我认为 PAUSE 指令不会提高循环的性能。 IN 指令不访问普通内存,因此不会因为写入其他 CPU 的内存而导致流水线被刷新。由于 IN 指令也不能被推测执行,因此流水线中一次只能有一条 IN 指令,因此在循环结束时这种错误预测的分支的成本会相对较小。它可能具有该答案中提到的其他好处,即降低功耗并为超线程处理器上的其他逻辑 CPU 提供更多执行资源。

    并不是说它真的很重要。在现代处理器上,键盘控制器发送或接收单个字节需要超过一百万个周期,甚至需要几百个周期,因为一些最坏情况下的管道停顿并不重要。

    【讨论】:

    • 您可能想要添加(在第 2 段中)现代 CPU 推测的不仅仅是分支预测。他们还推测内存排序,这就是PAUSE 的帮助,通过防止错误推测。我不认为PAUSE 在这里会有所帮助。它只是将in 的启动延迟了 10 个周期(或者可能是 Skylake 上的 100c?)我假设当管道在 in 指令上阻塞时,另一个逻辑核心每个周期都会获得。我不认为PAUSE 对此有帮助。保持循环紧密可能意味着当前核心在被阻塞时需要更少的 ROB 条目。
    猜你喜欢
    • 1970-01-01
    • 2015-11-04
    • 2014-04-25
    • 2014-03-03
    • 2019-01-27
    • 2014-07-03
    • 2010-09-23
    • 2014-01-25
    • 2016-07-01
    相关资源
    最近更新 更多