Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 为什么在对齐和未对齐的情况下,此循环的循环计数相似?_Assembly_Optimization_X86 - Fatal编程技术网

Assembly 为什么在对齐和未对齐的情况下,此循环的循环计数相似?

Assembly 为什么在对齐和未对齐的情况下,此循环的循环计数相似?,assembly,optimization,x86,Assembly,Optimization,X86,我测试台上的cpu是IntelR CoreTM i5-3470 cpu@3.20GHz,所以它是常春藤桥和第三代intel core进程 我使用Agner Fog提供的数据进行分析 根据以下测试结果,如果我对齐asm代码,前失速周期将非常小,但指令或UOP的数量将增加。总体来说,核心周期是相似的 那么,我应该如何优化asm代码呢?或者我错在哪里 请注意最后一栏。据我所知,这意味着前失速,因此我尝试使用.align 16来减少失速,以获得更好的性能,您可以看到我使用了3.align,而RESOUR

我测试台上的cpu是IntelR CoreTM i5-3470 cpu@3.20GHz,所以它是常春藤桥和第三代intel core进程

我使用Agner Fog提供的数据进行分析

根据以下测试结果,如果我对齐asm代码,前失速周期将非常小,但指令或UOP的数量将增加。总体来说,核心周期是相似的

那么,我应该如何优化asm代码呢?或者我错在哪里

请注意最后一栏。据我所知,这意味着前失速,因此我尝试使用.align 16来减少失速,以获得更好的性能,您可以看到我使用了3.align,而RESOURCE_stall.ANY几乎为空

如果不添加.align 16,则测试结果:

  Clock    BrTaken   Core cyc   Instruct    Uops        Uops F.D.    rs any
60763677   49076140   66968169  229533042  164009900   164144552   17506254 
59512474   49076140   66856747  229533041  164003819   164133385   17481613
  Clock    BrTaken   Core cyc   Instruct     Uops       Uops F.D.     rs any 
73537615   49076140   82188535  311530045  246006910   246064159        3 
74063027   49076140   82217717  311530045  246002615   246067520        4 
如果我对齐asm代码,测试结果:

  Clock    BrTaken   Core cyc   Instruct    Uops        Uops F.D.    rs any
60763677   49076140   66968169  229533042  164009900   164144552   17506254 
59512474   49076140   66856747  229533041  164003819   164133385   17481613
  Clock    BrTaken   Core cyc   Instruct     Uops       Uops F.D.     rs any 
73537615   49076140   82188535  311530045  246006910   246064159        3 
74063027   49076140   82217717  311530045  246002615   246067520        4 
如果我移除第二个。对齐并移动标签前的第三个,结果:

     Clock    BrTaken   Core cyc   Instruct       Uops     rs any 
  59930621   49076358   66898617  245995143  180472213   17440098 
  59596305   49076140   66886858  245993040  180461441   17487217
柜台信息:

              event mask   comment
   BrTanken   0xa2  0x01   branches taken
   Uops       0xc2  0x01   uops retired, unfused domain.
   Uops F.D   0x0E  0x01   uops, fused domain, Sandy Bridge.
   rs any     0xa2  0x01   Cycles Allocation are stalled due to Resource Related reason.
   Instruct   0x40000000   Instructions (reference counter)
asm代码,我从gcc O1获得

.section .text
.globl sum_sort_O1
.type sum_sort_O1, @function
sum_sort_O1:
        movl    $100000, %esi
        movl    $0, %eax
        jmp     .L2 
#.align 16 --- 1
.L6:
        movl    (%rdi,%rdx), %ecx
        cmpl    $127, %ecx
        jle     .L3 
#.align 16 --- 2
        movslq  %ecx, %rcx
        addq    %rcx, %rax
.L3:
#.align 16 --- 3
        addq    $4, %rdx
        cmpq    $131072, %rdx
        jne     .L6 
        subl    $1, %esi
        je      .L5 
.L2:
        movl    $0, %edx
        jmp     .L6 
.L5:
        rep ret 
c代码:

#define  arraySize  32768

long long sort(int* data)
{
    long long sum = 0;
     for (unsigned i = 0; i < 100000; ++i)
    {   
        for (unsigned c = 0; c < arraySize; ++c)
        {   
            if (data[c] >= 128)
                sum += data[c];
        }   
    }   
}
============================================================== 性能间监视器事件

========================================================================= 优化

我正在看文件 64-ia-32-architectures-optimization-manual.pdf,我在附录B.1中找到了一种自上而下的分析方法。 我试着用这个方法优化这段代码

我遇到的第一个问题是分支预测失误,我们可以对数据进行排序以解决它

第二个问题是这个问题,前失速和后失速非常大。 如果我添加.align,失速会大大减少,但总时间不会减少。 所以我认为我的方向是正确的,但我的方法不好,这就是为什么我在这里列出问题来询问一些想法

我知道优化这段代码是一项很大的工作,我尝试用自顶向下的分析方法一步一步地优化它

========================================================================== 背景

我对这个问题很感兴趣

是的,作者遇到的问题是分支预测

当分支预测得到解决时,我想优化代码。

在某些情况下,调整loops0可能有助于某些架构的性能,但可能不会。特别是,当您省略一个显式指令时,可能是因为自然对齐仅为fine1

这种可能性有多大取决于对齐的重要性:比如说,如果循环体在从顶部开始的前5个字节的指令中跨越了16个字节的边界,就会受到惩罚:即使不强制对齐,如果入口点是随机分布的,发生这种情况的几率也只有约27%,所以在这种情况下,对齐通常没有区别

即使对齐消除了管道中某个部分(通常是前端)的惩罚,也很可能该组件不是整体瓶颈,因此避免惩罚不会提高最终性能

较新的x86 CPU还通过引入uop缓存等功能,在某些方面降低了代码对齐的影响,并具有总体更好的前端性能,例如,在Skylake上解码5条指令/周期,这使得前端不太可能成为瓶颈

更重要的是,在您的特定示例中,三个.align位置中的最后两个位于主循环的内部!这意味着为对齐而执行的指令可能会频繁执行,这意味着对齐可能会有很大的负面影响,而不是抵消任何收益。只有在很少执行对齐填充的情况下才需要对齐,例如在热循环之前,而不是在热循环内部!这个问题就是为什么在对齐的情况下指令计数会大幅跳跃

无论如何,对齐对这种具有密集非循环分支的算法几乎没有影响,除非所有这些分支都得到了很好的预测:相反,分支预测失误成本将占主导地位

0一般来说,这指的是对齐循环中的第一条指令,也称为循环顶部,但据我所知,其他类型的对齐可能也很有用,这些其他类型的对齐从未在编译器中实现过

1这与所谓的体系结构形成对比,因为体系结构在错误对齐内存访问时会受到惩罚。通常情况下,只有完全对齐的访问才能全速运行,但其他任何访问都未对齐并受到惩罚,对于特殊的未对齐情况,例如缓存线或跨页访问,可能会受到更大的惩罚。代码对齐通常不是这样工作的:对齐只是一种启发式,通常有助于避免一些可能的惩罚,但可能还有其他未对齐的配置也可以避免惩罚。

代码中有三个.align 16实例。第二个似乎是com
完全不适合我,我想你应该把它拿走。第三个需要放在标签前面,而不是标签后面。这是适得其反的。我很想知道这些建议是如何影响你的结果的。我不确定你是想提高这段代码的性能,还是只是想知道它为什么会这样。如果是前者,您可以卸下jle并用cmovle更换。您还可以删除movslq。ecx已知大于0,rcx的上半部分已知为0。@prl,我正在尝试优化它。在另一个测试用例中,我使用cmovl来减少分支,虽然结果与此类似,但从我的角度来看,原因是数据已被排序。@prl,我不明白你的意思,它在实际情况下会适得其反。我很想知道这些建议是如何影响你的结果的,你的意思是我为什么要加上?或?align指令的目的是对齐跳转的目标。但是由于标签在对齐之前,跳转的目标是未对齐的,并且它必须执行由对齐插入的所有NOP。您好,BeeOnRope,在本例中,我观察到rs.any非常高,据我所知,它意味着前失速,因此我尝试通过添加对齐来减少它。rs.any减少到几乎为0,但指令和UOP增加了,因此有没有一种方法可以减少rs.any而不是增加指令,这样就可以减少核心周期。rs事件有一些子类别,您可以检查这些子类别,它们告诉您组成all数的组件,因此这是需要检查的。不过,资源暂停计数器可能会产生误导:仅仅减少它们并不一定会提高性能:您可以有大量的资源暂停,但实际的瓶颈可能在其他地方,因此将资源暂停减少到零可能几乎没有任何影响,或者可能会产生非常大的影响。尽管如此,你现在确实在问一个关于优化的更一般的问题——为什么不创建一个新的问题呢?@尽管如此,最肯定的是,循环的对齐不会是这里挂不住的果实——首先会有很多事情要做。用include MCVE提出你的另一个问题,特别是描述你感兴趣的输入数据的分布。我部分同意你的想法,循环对齐可能不会减少核心周期,优化这部分代码是一项艰巨的工作。但从我的角度来看,我的方向是正确的,我遵循文档64-ia-32-architectures-optimization-manual中的方法自上而下的分析方法。我试图一步一步地优化代码,现在我遇到了这个问题并试图解决它。谢谢BeeOnRope,我明白你的想法,你给了我一个方向,我将更多地阅读toplev.py。也许我会用它来做更多的分析,并在遇到新问题时创建一个新的查询。