Optimization 太多的周期 我考虑从Agner Fog优化汇编的例子。他测试: 例12.6b。DAXPY算法,32位模式

Optimization 太多的周期 我考虑从Agner Fog优化汇编的例子。他测试: 例12.6b。DAXPY算法,32位模式,optimization,x86,Optimization,X86,他在奔腾M上估计了大约6个循环/迭代。我也尝试过,但在我的CPU-常春藤桥接器上。我每次迭代达到3个循环,但从我的纸上计算,有可能得到2个循环。我不知道我是不是在理论计算上犯了错误,还是可以改进 我所做的: 据我所知,我的CPU可以使4个微操作周期失效,所以这不是一个瓶颈 #uops fused = 8 / 4 = 2 因此,2是当前我们的瓶颈。让我们看看另一种可能性: Microps有模式:1-1-1-1-1-1-1-1-1,根据Agner Fog的说法,我的CPU有模式1-1-1-1(和

他在奔腾M上估计了大约6个循环/迭代。我也尝试过,但在我的CPU-常春藤桥接器上。我每次迭代达到3个循环,但从我的纸上计算,有可能得到2个循环。我不知道我是不是在理论计算上犯了错误,还是可以改进

我所做的:

据我所知,我的CPU可以使4个微操作周期失效,所以这不是一个瓶颈

#uops fused = 8 / 4 = 2
因此,
2
是当前我们的瓶颈。让我们看看另一种可能性:

Microps有模式:1-1-1-1-1-1-1-1-1,根据Agner Fog的说法,我的CPU有模式1-1-1-1(和其他)。由此我们可以看出,在2个周期内解码指令是可能的。这不是瓶颈。此外,SnB CPU具有微缓存,因此取数和解码都不应成为瓶颈

#uops fused = 8 / 4 = 2
指令的大小(以字节为单位)是32,所以它适合微缓存窗口(32字节)

根据我的实验,当我添加
nop
指令时,它会增加每个迭代的周期数(大约0.5个周期)

因此,问题是:


那一个周期在哪里D

您确定不受内存带宽的限制吗?您需要使用适合一级缓存的阵列进行测试,因为每两个时钟需要两次加载和一次存储。(这是IvB理论上每个时钟最多两个128b内存操作的一半以上,其中最多一个是存储器。)


解码不相关,因为循环适合循环缓冲区。(低于28个计量单位)。因此,它只是以4个已经解码的UOP为一组发布


您的融合域uop计数错误<代码>cmp/jl可以将宏融合到一个比较和分支uop中。然而,这一错误被另一个错误所抵消,因为阿格纳·福格的指南中还没有这一错误

movapd[edi+eax],xmm0不能在IvB上进行微融合,因此它是2个融合域UOP

我最近在英特尔的优化手册中找到了官方确认,该手册解释了Agner的测试与我的测试的不同结果:这种寻址模式可以在解码器和uop缓存中微融合,但在OOO内核中不能。(见我对这个问题的回答。我应该再给阿格纳发一条信息,让他知道英特尔的文件解决了我们的困惑…)

试试这个:

    add    ecx, edi          ; end-of-Y pointer
    sub    esi, edi          ; esi = X-Y
L1:
    movapd xmm1, [esi+edi]   ; 1 uop
    mulpd  xmm1, xmm2        ; 1 uop
    movapd xmm0, [edi]       ; 1 uop
    subpd  xmm0, xmm1        ; 1 uop
    movapd [edi], xmm0       ; 1 micro-fused uop
    add edi, 16              ; 1 uop
    cmp edi, ecx             ; loop while (dst < end_Y)
    jb L1                    ; cmp+jb = 1 macro-fused uop
添加ecx、edi;Y端指针
电子数据交换小组;esi=X-Y
L1:
movapd xmm1,[esi+edi];1 uop
mulpd xmm1,xmm2;1 uop
movapd xmm0[edi];1 uop
子分区xmm0,xmm1;1 uop
movapd[edi],xmm0;1微熔合uop
增加电子数据交换,16;1 uop
cmp-edi,ecx;循环时(dst<结束时)
jbl1;cmp+jb=1宏观熔断uop
负载不需要微熔合,但存储为2个熔合域UOP。(存储地址和存储数据)

我会告诉你这家店只有2个uops,不能进行微熔断。值得一看。有时它的数字是错误的(例如,它认为shrd在SnB上仍然很慢),但通常只要你意识到它是对真实硬件行为的简单近似,而不是一个周期精确的模拟器,它就很有用


我的版本是7总融合域UOP。因此,它应该在SnB系列CPU上每2个时钟运行一次迭代。您的原始版本是8 uops,因此此更改不会产生任何影响。在注意到您并没有考虑cmp/jcc的宏融合之前,我写了它,所以我认为您的循环实际上是9个UOP。由于添加一个
nop
会降低代码的速度,这进一步证明它是8个融合域UOP。如果使用太大的阵列进行测试时缓存未命中不能解释这一点,那么可能IvB在调度加载/存储UOP方面做得不好?似乎不太可能,因为它们都必须使用端口2或3作为存储地址或加载UOP。(在未使用的域中,存储数据UOP转到端口4)


你确定你的循环每3个周期就有一次迭代吗?添加一个
nop
可能会使其速度减慢,因为9 uop循环应该在3个周期内发出。

1。谢谢!:)2.你显然是对的。我在2048和4096个数组元素上测试了我的代码(因此它适合于L1),事实上,我每次迭代大约需要2个周期。3.“如果使用太大的数组测试时缓存未命中,这并不能解释,”他们确实解释了这一点——当我制作更大的数组时,每次迭代都会增加一些周期。4.我仍然有一个问题,UOP融合到底意味着什么。我知道它的字面意思是什么-一些UOP被加入。但是如何做到呢?阿格纳·福格的《微阵列指南》和英特尔的《优化手册》应该对uop的微观和宏观融合有一个像样的解释。在Agner Fog的Microach pdf中,他在为第一个实现它的CPU描述fusion时详细介绍了它:奔腾M。参见第90/91页:“Section 7.6 Micro op fusion”大约有2页长。我并不是试图在每一个答案中对每一件事都进行完整的解释,这将花费很长时间。这就是为什么我刚刚链接到另一个关于SnB系列CPU上索引寻址模式微融合的答案。当然你需要阅读链接。谢谢。我没有要求你解释一切。链接,其他参考都可以。