Performance 在Skylake上展开1周期循环会降低25%的性能。uops调度问题?

Performance 在Skylake上展开1周期循环会降低25%的性能。uops调度问题?,performance,assembly,x86,intel,perf,Performance,Assembly,X86,Intel,Perf,TL;DR我有一个循环,在Skylake上执行需要1个周期(它执行3次添加+1次inc/跳跃) 当我将它展开超过2次(无论多少次)时,我的程序运行速度大约慢25%。这可能与对齐有关,但我不清楚是什么 编辑:该问题用于询问为什么UOP由DSB而不是MITE交付。现在已将此移到 我试图对一个循环进行基准测试,该循环在我的Skylake上进行了3次添加。这个循环应该在一个周期内执行,因为3加+1增量与条件跳转融合,一旦融合,可以在一个周期内执行。果然如此 然而,在某个时刻,我的C编译器试图展开该循环

TL;DR我有一个循环,在Skylake上执行需要1个周期(它执行3次添加+1次inc/跳跃)

当我将它展开超过2次(无论多少次)时,我的程序运行速度大约慢25%。这可能与对齐有关,但我不清楚是什么

编辑:该问题用于询问为什么UOP由DSB而不是MITE交付。现在已将此移到


我试图对一个循环进行基准测试,该循环在我的Skylake上进行了3次添加。这个循环应该在一个周期内执行,因为3加+1增量与条件跳转融合,一旦融合,可以在一个周期内执行。果然如此

然而,在某个时刻,我的C编译器试图展开该循环,从而导致性能下降。我现在试图理解为什么展开的循环的性能比未展开的循环差,因为我希望两者的性能相同,或者展开的循环的性能比未展开的循环差

这是我的C代码:

intmain(){
INTA、b、c、d;
#布拉格展开(2)
对于(无符号长i=0;i<2000000;i++){
asm volatile(“:“+r”(a),“+r”(b),“+r”(c),“+r”(d));
a=a+d;
b=b+d;
c=c+d;
}
//防止数据被优化
asm volatile(“:“+r”(a),“+r”(b),“+r”(c));
}
使用Clang 7.0.0-O3编译将生成以下(已清理的)程序集(从现在起称为
v1
):

使用
perf stat-e cycles
进行基准测试表明,每次迭代大约需要2个周期

但是,用“新的64位寄存器”(r8到r15)替换任何寄存器会导致循环以3个周期而不是2个周期执行(我们称此代码为
v2
):

这不是一个随机的例子:如果我在我的程序中添加了一些东西,并且运气不好,那么Clang实际上会产生这个循环(我的初始版本是相同的C代码,另外随机初始化变量、预热阶段和rdtscp来计时循环,Clang在循环中使用了
r14d
)。此循环以大约3个周期/迭代执行

进一步的测试表明,如果循环展开次数大于2,则程序执行周期为25亿次(非展开循环为20亿次)

循环中的UOP数为
3*n+1
(其中
n
为展开因子,
1
表示融合的
add/jne
),这意味着展开3次的循环有10个UOP;4乘以13个uop等。这些uop的数量相当小,应该放在DSB(uop缓存)中。我和你在天湖上

此外,展开3、4、10或50次根本不会改变性能:我的代码总是以25亿个周期运行(而未展开的代码则以20亿个周期运行)。这有点令人惊讶,因为3个加法应该总是在1个周期内执行,因此,如果由于某种原因在循环结束时损失了一个额外的周期,它的开销应该在展开增加时摊销,渐进(在展开因子中)性能应该接近20亿个周期

llvmmca
iaca
都预测,展开n次将使循环以n个周期执行(这将使整个程序以20亿个周期执行)


总而言之,问题是:为什么我的循环一展开超过2次就慢了25%?

评论不用于扩展讨论;这段对话已经结束。
    movl    $2000000000, %esi
    .p2align    4, 0x90
.LBB0_1:
    addl    %edi, %edx
    addl    %edi, %ecx
    addl    %edi, %eax
    addl    %edi, %edx
    addl    %edi, %ecx
    addl    %edi, %eax
    addq    $-2, %rsi
    jne .LBB0_1
    movl    $2000000000, %esi
    .p2align    4, 0x90
.LBB0_1:
    addl    %edi, %r14d
    addl    %edi, %ecx
    addl    %edi, %eax
    addl    %edi, %r14d
    addl    %edi, %ecx
    addl    %edi, %eax
    addq    $-2, %rsi
    jne .LBB0_1