什么是局部标志失速?

Eva*_*oll 6 x86 assembly

我刚刚查看了彼得·科德斯(Peter Cordes)的回答,他说,

如果读取标志,则部分标志停顿会发生,如果它们确实发生的话。P4永远不会有部分标志停顿,因为它们永远不需要合并。相反,它具有错误的依赖关系。几个答案/评论混淆了术语。它们描述了一个错误的依赖关系,但随后将其称为部分标志停顿。这是由于仅写入一些标志而导致的速度下降,但是术语“部分标志停顿”是指必须合并部分标志写入时在SnB之前的Intel硬件上发生的情况。英特尔SnB系列CPU插入一个额外的uop来合并标志而不会停顿。Nehalem和更早的失速约7个周期。我不确定AMD CPU会受到多大的损失。

我感觉我还不明白什么是“部分国旗摊位”。我怎么知道一个人发生了?除了读取标志的某些时间之外,什么触发事件?合并标志是什么意思?在什么情况下会“写一些标志”,但不会发生部分标志合并?我需要了解哪些有关旗位的知识才能理解它们?

Bee*_*ope 7

一般而言,当标志消耗指令读取一个或多个最近的标志设置指令未写入的标志时,就会发生部分标志停顿。

因此,像这样的指令inc仅设置了一些标志(未设置CF)不会固有地导致部分停顿,但是如果随后的指令读取CF未设置的标志(),则将导致停顿inc(没有任何中间指令设置CF标志)。这也意味着写所有有趣标志的指令永远不会涉及部分停顿,因为当它们是执行标志读取指令时最新的标志设置指令时,它们必须已经写入消耗的标志。

因此,通常,一种用于静态确定是否会发生部分标志停顿的算法是查看使用这些标志的每条指令(通常是jccfamily和cmovcc一些专门的指令,例如adc),然后向后走以找到设置该标志的第一条指令任何标志,并检查它是否设置了使用指令读取的所有标志。否则,将发生部分标志停顿。

从Sandy Bridge开始的后来的体系结构本身并不会遭受部分标志停顿,但是在某些情况下,指令还会在前端添加额外的uop形式,因此会受到惩罚。与以上讨论的摊位相比,规则略有不同,适用于范围更窄的案件。特别地,仅当标志消耗指令从多个标志读取并且那些标志最后由不同指令设置时,才添加所谓的标志合并uop。例如,这意味着检查单个标志的指令绝不会导致发出合并的uop。

例子

这里有些例子。我们同时讨论了“ [partial flag]停顿”和“ merge uops”,但如上所述,最多只有两者之一适用于任何给定的体系结构,因此应使用“以下内容导致停顿和合并uop发出”之类的东西理解为“以下内容导致[在具有部分标志停顿的较旧体系结构上出现停顿]或[在使用合并uops替代的较新体系结构上]合并uop”。

停转和合并

以下示例将导致发出停顿和合并uop:

add rbx, 5   ; sets CF, ZF, others
inc rax      ; sets ZF, but not CF
ja  label    ; reads CF and ZF
Run Code Online (Sandbox Code Playgroud)

ja指令读取CFZF其通过最后一组addinc指令,分别,所以合并UOP被插入到统一分别设置的标志用于通过消耗ja。在停顿的体系结构上,发生停顿是因为最新标志设置指令未设置ja从中读取的内容CF

注意:我们认为我们所知道的似乎不再正确,请参阅注释。上面的序列实际上并不会导致Skylake以及早期体系结构上的合并uop。我离开上面的内容,因为它代表了此事上的“常规智慧”,但这至少是部分错误的。

仅停转

add rbx, 5   ; sets CF, ZF, others
inc rax      ; sets ZF, but not CF
jc  label    ; reads CF
Run Code Online (Sandbox Code Playgroud)

这将导致停顿,因为如在先前示例CF中那样,读取的是最后标志设置指令(此处为inc)未设置的。在这种情况下,可以通过简单地交换和的顺序来避免停顿incadd因为它们是独立的,然后jc仅从最近的标志设置操作中读取。不需要合并uop,因为已读标志(仅CF)全部来自同一add指令。

注意:此案尚在辩论中(请参阅评论)-但我无法对其进行测试,因为我在Skylake上根本找不到任何合并操作的证据。

没有失速或合并

add rbx, 5   ; sets CF, ZF, others
inc rax      ; sets ZF, but not CF
jnz  label   ; reads ZF
Run Code Online (Sandbox Code Playgroud)

即使最后一条指令(inc)仅设置了一些标志,在这里也没有停顿或合并uop的需要,因为使用jnz仅读取由inc和设置的标志(的一个子集)而没有其他标志。因此,这种常见的循环习惯(通常使用dec而不是inc)不会固有地引起问题。

这是另一个不会导致停顿或合并uop的示例:

inc rax      ; sets ZF, but not CF
add rbx, 5   ; sets CF, ZF, others
ja  label    ; reads CF and ZF
Run Code Online (Sandbox Code Playgroud)

此处ja的确读取了CF和未设置的ZFan和an (即,部分标志写入指令),但没有问题,因为出现在and 之后,并写入了所有相关标志。incZFaddinc

转变

变速指令sarshrshl比上述在两个其可变和固定数形式表现不同(通常更差),并且该跨架构而变化相当数量。这可能是由于它们的标志处理异常且不一致1所致。例如,在许多体系结构上,在移位计数为1以外的移位指令后读取任何标志时,都会出现部分标志停顿的情况。即使在最新的体系结构上,由于标志处理,变量移位的成本也高达3微秒(但没有更多的“停转”)。

我不会在此处包括所有细节,但如果您需要所有细节,建议您在Agner的microarch 文档中查找单词转移

在某些情况下,某些轮换指令还具有与标志相关的有趣行为,类似于移位。


1例如,根据移位计数是0、1还是其他某个值来设置标志的不同子集。


归档时间:

查看次数:

291 次

最近记录:

5 年,9 月 前