当前位置: 首页 > 知识库问答 >
问题:

分支预测器的预测中是否也包括I/O指令?

谭景福
2023-03-14

我目前正在编写一个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

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

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

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

共有1个答案

莘聪
2023-03-14

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

您链接的答案中建议的暂停指令并不意味着会影响分支预测器。这是为了防止当该问题的示例代码中的CMP指令所访问的内存位置被另一个处理器写入时发生流水线停顿。CMP指令也不会影响分支预测。

彼得·科德斯提到,你可能会被CPU用来推测性地执行指令的不同技术弄糊涂,以保持管道满。在你链接的问题中,推测性执行最终会损害自旋锁的性能有两种不同的方式。两者都有一个共同的根源,CPU试图尽可能快地执行循环,但实际上影响自旋锁性能的是它从循环中出来的速度。只有循环最终迭代的速度才重要。

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

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

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

 类似资料:
  • 如果语句更多地依赖于分支预测,而v表查找更多地依赖分支目标预测,那么

  • 分支目标预测(BTP)与分支预测(BP)不同。我知道BTP会找到分支将跳转到的位置,而BP只是决定可能采取哪个分支。 BTP依赖BP吗,如果BTP不使用BP来预测哪个分支被采用,它怎么可能知道分支的目标呢? 我不明白为什么会有这么大的差异?一旦分支被预测为被占用,找到目标并不像读取指令中的地址一样简单吗?

  • 编辑:我的困惑出现了,因为通过预测哪个分支,你肯定也在有效地进行目标预测?? 这个问题与我关于这个主题的第一个问题有内在联系: 分支预测与分支目标预测 无限循环 语句 或语句 语句的“then”子句结尾(跳过子句) 非虚函数调用 从函数返回 虚函数调用 函数指针调用 语句(如果编译为跳转表) 语句 语句(如果编译成一系列语句) 循环条件测试 和运算符 三元运算符 null 如果我有以下代码: (B

  • 我的代码经常调用具有多个(不可预测的)分支的函数。当我分析时,我发现这是一个小瓶颈,大部分CPU时间用于条件JMP。 考虑以下两个函数,其中原始函数有多个显式分支。 这是一个新函数,我试图在其中删除导致瓶颈的分支。 然而,当我分析新代码时,性能只提高了大约20%,而且调用本身(对mem_funcs数组中的一个func)花费了很长时间。 第二个变量仅仅是一个更隐含的条件吗,因为CPU仍然无法预测将要

  • 我有一个与相关预测因子相关的练习,它指出以下几点: 答:贝兹·R1,D … D:贝兹·R1,F … F:不是R1的R1 预测工作如下 > 获取当前指令 如果是分支,则确定预测器的当前状态并预测分支: a.row 由分支地址确定(在本例中为 A 或 D) b. 列由当前全局移位寄存器确定 c.使用单元格中的值确定来自状态机的预测(当前状态保存在单元格中) 执行分支,并确定实际决策(已采取:1,未采取

  • 我正在编写一些音频代码,其中基本上所有内容都是一个小循环。据我所知,分支预测失败是一个足够大的性能问题,我很难保持代码分支的自由。但是只有这么远的时间才能带我,这让我想知道不同类型的分支。 在 c 中,固定目标的条件分支: 并且(如果我正确理解这个问题),无条件分支到变量目标: 是否存在性能差异?在我看来,如果这两种方法中的一种明显快于另一种,编译器只需将代码转换为匹配即可。 对于那些分支预测非常