热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

两个看似相同的汇编代码之间的性能差异

如何解决《两个看似相同的汇编代码之间的性能差异》经验,为你挑选了1个好方法。

tl; dr:我有两个功能相同的C代码,我用Clang编译(事实上它的C代码并不重要;只有汇编很有意思),IACA告诉我一个应该更快,但我不明白为什么,我的基准测试显示两个代码的性能相同.

我有以下的C代码(忽略#include "iacaMarks.h",IACA_START,IACA_END现在):

ref.c:

#include "iacaMarks.h"
#include 

#define AND(a,b)  _mm_and_si128(a,b)
#define OR(a,b)   _mm_or_si128(a,b)
#define XOR(a,b)  _mm_xor_si128(a,b)
#define NOT(a)    _mm_andnot_si128(a,_mm_set1_epi32(-1))

void sbox_ref (__m128i r0,__m128i r1,__m128i r2,__m128i r3,
               __m128i* r5,__m128i* r6,__m128i* r7,__m128i* r8) {
  __m128i r4;

  IACA_START
  r3 = XOR(r3,r0);
  r4 = r1;
  r1 = AND(r1,r3);
  r4 = XOR(r4,r2);
  r1 = XOR(r1,r0);
  r0 = OR(r0,r3);
  r0 = XOR(r0,r4);
  r4 = XOR(r4,r3);
  r3 = XOR(r3,r2);
  r2 = OR(r2,r1);
  r2 = XOR(r2,r4);
  r4 = NOT(r4);
  r4 = OR(r4,r1);
  r1 = XOR(r1,r3);
  r1 = XOR(r1,r4);
  r3 = OR(r3,r0);
  r1 = XOR(r1,r3);
  r4 = XOR(r4,r3);
  *r5 = r1;
  *r6 = r4;
  *r7 = r2;
  *r8 = r0;
  IACA_END

}

我想知道我是否可以通过手动重新安排一些指令来优化它(我很清楚C编译器应该产生一个有效的调度,但是我的实验已经表明它并非总是如此).在某些时候,我尝试下面的代码(这是与上面相同,不同之处在于没有临时变量用于存储后来被分配到异或结果*r5*r6):

resched.c:

#include "iacaMarks.h"
#include 

#define AND(a,b)  _mm_and_si128(a,b)
#define OR(a,b)   _mm_or_si128(a,b)
#define XOR(a,b)  _mm_xor_si128(a,b)
#define NOT(a)    _mm_andnot_si128(a,_mm_set1_epi32(-1))

void sbox_resched (__m128i r0,__m128i r1,__m128i r2,__m128i r3,
                   __m128i* r5,__m128i* r6,__m128i* r7,__m128i* r8) {
  __m128i r4;

  IACA_START
  r3 = XOR(r3,r0);
  r4 = r1;
  r1 = AND(r1,r3);
  r4 = XOR(r4,r2);
  r1 = XOR(r1,r0);
  r0 = OR(r0,r3);
  r0 = XOR(r0,r4);
  r4 = XOR(r4,r3);
  r3 = XOR(r3,r2);
  r2 = OR(r2,r1);
  r2 = XOR(r2,r4);
  r4 = NOT(r4);
  r4 = OR(r4,r1);
  r1 = XOR(r1,r3);
  r1 = XOR(r1,r4);
  r3 = OR(r3,r0);
  *r7 = r2;
  *r8 = r0;
  *r5 = XOR(r1,r3); // This two lines are different
  *r6 = XOR(r4,r3); // (no more temporary variables)
  IACA_END
}

我正在使用Clang 5.0.0编译这些代码,目标是我的i5-6500(Skylake),带有标志-O3 -march=native(我省略了汇编代码,因为它们可以在IACA输出中找到,但如果你更喜欢把它们直接放在这里,问我,我会加上它们.我对这两个代码进行了基准测试,但没有发现它们之间有任何性能差异.出于好奇,我在他们身上运行了IACA,我惊讶地发现它说第一个版本应该运行6个周期,第二个版本需要7个周期.以下是IACA的产出:

对于第一个版本:

dada@dada-ubuntu ~/perf % clang -O3 -march=native -c ref.c && ./iaca -arch SKL ref.o        
Intel(R) Architecture Code Analyzer Version -  v3.0-28-g1ba2cbb build date: 2017-10-23;16:42:45
Analyzed File -  ref_iaca.o
Binary Format - 64Bit
Architecture  -  SKL
Analysis Type - Throughput

Throughput Analysis Report
--------------------------
Block Throughput: 6.00 Cycles       Throughput Bottleneck: FrontEnd
Loop Count:  23
Port Binding In Cycles Per Iteration:
--------------------------------------------------------------------------------------------------
|  Port  |   0   -  DV   |   1   |   2   -  D    |   3   -  D    |   4   |   5   |   6   |   7   |
--------------------------------------------------------------------------------------------------
| Cycles |  6.0     0.0  |  6.0  |  1.3     0.0  |  1.4     0.0  |  4.0  |  6.0  |  0.0  |  1.4  |
--------------------------------------------------------------------------------------------------

DV - Divider pipe (on port 0)
D - Data fetch pipe (on ports 2 and 3)
F - Macro Fusion with the previous instruction occurred
* - instruction micro-ops not bound to a port
^ - Micro Fusion occurred
# - ESP Tracking sync uop was issued
@ - SSE instruction followed an AVX256/AVX512 instruction, dozens of cycles penalty is expected
X - instruction not supported, was not accounted in Analysis

| Num Of   |                    Ports pressure in cycles                         |      |
|  Uops    |  0  - DV    |  1   |  2  -  D    |  3  -  D    |  4   |  5   |  6   |  7   |
-----------------------------------------------------------------------------------------
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm4, xmm3, xmm0
|   1      |             | 1.0  |             |             |      |      |      |      | vpand xmm5, xmm4, xmm1
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm1, xmm2, xmm1
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm5, xmm5, xmm0
|   1      |             | 1.0  |             |             |      |      |      |      | vpor xmm0, xmm3, xmm0
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm0, xmm0, xmm1
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm1, xmm4, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm3, xmm4, xmm2
|   1      |             |      |             |             |      | 1.0  |      |      | vpor xmm2, xmm5, xmm2
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm2, xmm2, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpcmpeqd xmm4, xmm4, xmm4
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm1, xmm1, xmm4
|   1      | 1.0         |      |             |             |      |      |      |      | vpor xmm1, xmm5, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm4, xmm5, xmm3
|   1      |             |      |             |             |      | 1.0  |      |      | vpor xmm3, xmm0, xmm3
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm4, xmm4, xmm3
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm4, xmm4, xmm1
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm1, xmm1, xmm3
|   2^     |             |      | 0.3         | 0.3         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rdi], xmm4
|   2^     |             |      | 0.3         | 0.3         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rsi], xmm1
|   2^     |             |      | 0.3         | 0.3         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rdx], xmm2
|   2^     |             |      | 0.3         | 0.3         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rcx], xmm0
Total Num Of Uops: 26

对于第二个版本:

dada@dada-ubuntu ~/perf % clang -O3 -march=native -c resched.c && ./iaca -arch SKL resched.o
Intel(R) Architecture Code Analyzer Version -  v3.0-28-g1ba2cbb build date: 2017-10-23;16:42:45
Analyzed File -  resched_iaca.o
Binary Format - 64Bit
Architecture  -  SKL
Analysis Type - Throughput

Throughput Analysis Report
--------------------------
Block Throughput: 7.00 Cycles       Throughput Bottleneck: Backend
Loop Count:  22
Port Binding In Cycles Per Iteration:
--------------------------------------------------------------------------------------------------
|  Port  |   0   -  DV   |   1   |   2   -  D    |   3   -  D    |   4   |   5   |   6   |   7   |
--------------------------------------------------------------------------------------------------
| Cycles |  6.0     0.0  |  6.0  |  1.3     0.0  |  1.4     0.0  |  4.0  |  6.0  |  0.0  |  1.3  |
--------------------------------------------------------------------------------------------------

DV - Divider pipe (on port 0)
D - Data fetch pipe (on ports 2 and 3)
F - Macro Fusion with the previous instruction occurred
* - instruction micro-ops not bound to a port
^ - Micro Fusion occurred
# - ESP Tracking sync uop was issued
@ - SSE instruction followed an AVX256/AVX512 instruction, dozens of cycles penalty is expected
X - instruction not supported, was not accounted in Analysis

| Num Of   |                    Ports pressure in cycles                         |      |
|  Uops    |  0  - DV    |  1   |  2  -  D    |  3  -  D    |  4   |  5   |  6   |  7   |
-----------------------------------------------------------------------------------------
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm4, xmm3, xmm0
|   1      |             | 1.0  |             |             |      |      |      |      | vpand xmm5, xmm4, xmm1
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm1, xmm2, xmm1
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm5, xmm5, xmm0
|   1      |             | 1.0  |             |             |      |      |      |      | vpor xmm0, xmm3, xmm0
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm0, xmm0, xmm1
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm1, xmm4, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm3, xmm4, xmm2
|   1      |             |      |             |             |      | 1.0  |      |      | vpor xmm2, xmm5, xmm2
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm2, xmm2, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpcmpeqd xmm4, xmm4, xmm4
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm1, xmm1, xmm4
|   1      | 1.0         |      |             |             |      |      |      |      | vpor xmm1, xmm5, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm4, xmm5, xmm3
|   1      |             |      |             |             |      | 1.0  |      |      | vpor xmm3, xmm0, xmm3
|   2^     |             |      | 0.3         | 0.4         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rdx], xmm2
|   2^     |             |      | 0.3         | 0.3         | 1.0  |      |      | 0.4  | vmovdqa xmmword ptr [rcx], xmm0
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm0, xmm4, xmm3
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm0, xmm0, xmm1
|   2^     |             |      | 0.4         | 0.3         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rdi], xmm0
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm0, xmm1, xmm3
|   2^     |             |      | 0.3         | 0.4         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rsi], xmm0
Total Num Of Uops: 26
Analysis Notes:
Backend allocation was stalled due to unavailable allocation resources.

正如您所看到的,在第二个版本中,IACA表示瓶颈是后端,并且"后端分配由于不可用的分配资源而停滞".

两个汇编代码都包含相同的指令,唯一的区别是最后7条指令的调度,以及它们使用的寄存器.

我唯一可以想到的就是解释为什么第二个代码较慢的原因是它xmm0在最后4个指令中写入两次,从而引入了一个依赖.但由于这些写操作是独立的,我希望CPU为它们使用不同的物理寄存器.但是,我无法真正证明这一理论.此外,如果使用两次xmm0这样的问题,我希望Clang为其中一条指令使用不同的寄存器(特别是因为这里的寄存器压力很低).

我的问题:第二个代码应该更慢(基于汇编代码),为什么?

编辑:IACA跟踪:

第一版:https://pastebin.com/qGXHVW6a
第二版:https://pastebin.com/dbBNWsc2


注意:C代码是Serpent密码的第一个S-box的实现,由Osvik 在这里计算.



1> Hadi Brais..:

弄清楚为什么第二个代码是后端绑定需要一些手动分析,因为IACA发出的输出太粗糙,尽管信息非常丰富.请注意,IACA发出的迹线对于分析循环特别有用.它们对于理解指令的直线序列如何执行(这不是很有用)也很有用,但需要对发出的迹线进行不同的解释.通过这个答案的其余部分,我将展示我对循环场景的分析,这更难做到.

您在不将代码放入循环的情况下发出跟踪的事实会影响以下事项:

编译器无法内联并优化存储到输出操作数.它们不会出现在真正的循环中,或者将其链接到不同的S-box.

从输出到输入的数据依赖性是巧合发生的,因为编译器使用xmm0..3来准备要存储的数据,而不是选择将哪个输出反馈到同一个S-box的哪个输入.

vpcmpeqd创建一个全1向量(不)会内联后吊出循环.

将有一个dec/jnz或等效的循环开销(可以宏端口融合到端口6的单个uop).

但是你已经要求IACA分析这个确切的asm块,好像它是在循环中运行一样.因此,为了解释结果,我们将如何看待它(即使它不是你从C编译器得到的,如果你在循环中使用这个函数).

在这种情况下,A jmpdec/jnz底部使这个循环不是问题:它总是在端口6上执行,任何向量指令都不使用它.这意味着跳转指令不会在端口6上进行竞争,并且不会消耗本来由其他指令使用的调度程序uop带宽.但是,这会影响发布/重命名阶段的资源分配器带宽(每个周期不超过4个融合域uop),但这在我将讨论的特定情况下并不重要.

我们先来看一下端口压力ASCII数字:

| Num Of   |                    Ports pressure in cycles                         |      |
|  Uops    |  0  - DV    |  1   |  2  -  D    |  3  -  D    |  4   |  5   |  6   |  7   |
-----------------------------------------------------------------------------------------
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm4, xmm3, xmm0
|   1      |             | 1.0  |             |             |      |      |      |      | vpand xmm5, xmm4, xmm1
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm1, xmm2, xmm1
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm5, xmm5, xmm0
|   1      |             | 1.0  |             |             |      |      |      |      | vpor xmm0, xmm3, xmm0
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm0, xmm0, xmm1
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm1, xmm4, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm3, xmm4, xmm2
|   1      |             |      |             |             |      | 1.0  |      |      | vpor xmm2, xmm5, xmm2
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm2, xmm2, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpcmpeqd xmm4, xmm4, xmm4
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm1, xmm1, xmm4
|   1      | 1.0         |      |             |             |      |      |      |      | vpor xmm1, xmm5, xmm1
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm4, xmm5, xmm3
|   1      |             |      |             |             |      | 1.0  |      |      | vpor xmm3, xmm0, xmm3
|   2^     |             |      | 0.3         | 0.4         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rdx], xmm2
|   2^     |             |      | 0.3         | 0.3         | 1.0  |      |      | 0.4  | vmovdqa xmmword ptr [rcx], xmm0
|   1      | 1.0         |      |             |             |      |      |      |      | vpxor xmm0, xmm4, xmm3
|   1      |             | 1.0  |             |             |      |      |      |      | vpxor xmm0, xmm0, xmm1
|   2^     |             |      | 0.4         | 0.3         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rdi], xmm0
|   1      |             |      |             |             |      | 1.0  |      |      | vpxor xmm0, xmm1, xmm3
|   2^     |             |      | 0.3         | 0.4         | 1.0  |      |      | 0.3  | vmovdqa xmmword ptr [rsi], xmm0

融合域uop的总数为22.已经为端口0,1和5中的每一个分配了6个不同的uop.其他4个uop每个由STD和STA uop组成.STD需要端口4.此分配是合理的.如果我们忽略所有数据依赖性,那么调度程序应该能够在每个周期调度至少3个融合域uop.但是,在4号港口可能存在严重争用,这可能导致填满预订站.根据IACA,这不是此代码的瓶颈.请注意,如果调度程序可以某种方式实现等于分配器的最大吞吐量的吞吐量,则代码只能是前端绑定.显然,这不是这种情况.

下一步是仔细检查IACA跟踪.我根据跟踪制作了以下数据流图,更易于分析.水平黄线根据在同一周期中分配的uop来划分图形.请注意,IACA始终假设完美的分支预测.另请注意,此划分准确率约为99%,但不是100%.这并不重要,您可以认为它100%准确.节点表示融合的uops,箭头表示数据依赖性(箭头指向目标uop).节点根据它们属于哪个循环迭代而着色.为清楚起见,省略了图表顶部的箭头的来源.右侧的绿色框包含为相应的uops执行分配的循环编号.所以前一个周期是X,当前周期是X + 1,无论X是什么.停止标志表明相关的uop在其中一个端口遭受争用.所有红色停止标志代表端口1上的争用.只有另一个不同颜色的停止标志代表端口5上的争用.存在争用的情况,但为了清楚起见,我将省略它们.箭头有两种颜色:蓝色和红色.那些是关键的.注意,分配2次迭代的指令需要11个周期,然后重复分配模式.请记住,Skylake有97个RS.

每个部门("本地"位置)内的节点的位置具有含义.如果两个节点在同一行上,并且如果它们的所有操作数都可用,那么这意味着它们可以在同一个循环中调度.否则,如果节点不在同一行上,则可能不会在同一周期中调度它们.这仅适用于已作为一个组一起分配的动态uop,而不适用于作为不同组的一部分分配的动态uop,即使它们恰好位于图中的同一分区中.

在此输入图像描述

我将使用符号(it, in)来标识特定的融合uop,其中it是一个从零开始的循环迭代次数,并且in是一个从零开始的uop数.IACA跟踪中最重要的部分是显示(11,5)的管道阶段:

11| 5|vpxor xmm0, xmm0, xmm1                            :          |         |         |         |         |         |         |         |         |         |         |         |         |         |         
11| 5|    TYPE_OP (1 uops)                              :          |         |         |         |         |         |_A--------------------dw----R-------p  |         |         |         |         |         

这告诉我们由于资源不可用(在这种情况下,保留站中的条目),此时分配带宽未得到充分利用.这意味着调度程序无法维持足够高的未融合uop吞吐量,以跟上每个周期的前端4个融合uop.既然IACA已经告诉我们代码是后端绑定的,那么显然这种未充分利用的原因不是因为某些长的依赖链或特定执行单元的争用,而是更复杂的东西.所以我们需要做更多的工作来弄清楚发生了什么.我们必须分析过去(11,5).

每次迭代的uops 1,4,7,10,13,18都分配给端口1.在11个周期内会发生什么?总共有12个uop需要端口1,所以不可能在11个周期内调度它们,因为它至少需要12个周期.不幸的是,uops中需要相同端口和需要其他端口的uop的数据依赖性会显着加剧问题.在11个周期内考虑以下管道流程:

在周期0:(0,0)和(0,1)被分配(以及我们现在不关心的其他uops).(0,1)与数据有关(0,0).

1:(0,4)和(0,7)被分配.假设没有为端口0分配较旧的就绪uop并且(0,0)的操作数已准备好,则将端口0调度(0,0).端口1可能保持空闲,因为(0,1)尚未就绪.

2:(0,0)的结果可通过旁路网络获得.此时,(0,1)可以并将被发送.但是,即使(0,4)或(0,7)准备就绪,也不是最早的uop分配给端口1,因此它们都被阻止.(0,10)被分配.

3:(0,4)被分派到端口1.(0,7)和(0,10)即使它们的操作数准备就被阻止.(0,13)被分配.

4:(0,7)被分派到端口1.(0,10)被阻塞.(0,13)必须等待(0,7).(0,18)被分配.

5:(0,10)被分派到端口1.(0,13)被阻塞.(0,18)必须等待(0,17),这取决于(0,13).(1,0)和(1,1)得到分配.

6:(0,13)被分派到端口1.(0,18)必须等待(0,17),这取决于(0,13).(1,1)必须等待(1,0).因为(1,0)和(0,7)之间的距离是3微秒,其中一个可能遭受端口冲突,所以不能调度(1,0).(1,4)被分配.

7:没有任何东西被分派到端口1,因为(0,18),(1,1)和(1,4)没有准备好.(1,7)得到分配.

8:没有任何东西被分派到端口1,因为(0,18),(1,1),(1,4)和(1,7)没有准备好.(1,10)和(1,13)被分配.

9:(0,18)被分派到端口1.(1,10)和(1,4)准备好但由于端口争用而被阻止.(1,1),(1,7)和(1,13)没有准备好.

10:(1,1)被分派到端口1.(1,4),(1,7)和(1,10)准备好但由于端口争用而被阻止.(1,13)尚未准备好.(1,18)被分配.

好吧,理想情况下,我们希望在11个周期中将12个uop中的11个发送到端口1.但是这种分析表明情况远非理想.端口1在11个周期中有4个空闲!如果我们假设前一次迭代中的某些(X,18)在周期0被调度,则端口1将空闲3个周期,这是很多浪费,考虑到我们有12个uop需要每11个周期.在12个uops中,最多只有8个被派遣.情况有多糟糕?我们可以继续分析跟踪并记录如何准备分派但由于冲突而阻塞的p1绑定的uop的数量,或者由于数据不足而未准备好的p1绑定的uop的数量.我能够确定由于端口冲突而停滞的p1绑定的uop的数量永远不会大于3.然而,由于数据的不足导致的p1绑定的uops数量随着时间的推移逐渐增加.我没有看到任何模式增加的方式,所以我决定在跟踪的前24个周期使用线性回归来预测在什么时候会有97个这样的uop.下图显示了这一点.

在此输入图像描述

x轴表示从左到右增加的从零开始的循环.请注意,前4个周期的uop数为零.y轴表示相应周期的这种微量的数量.线性回归方程是:

y = 0.3624x - 0.6925.

通过将y设置为97,我们得到:

x =(97 + 0.6925)/0.3624 = 269.57

也就是说,在大约269周期,我们期望RS中有97个uop,所有p1-bound并等待它们的操作数准备就绪.此时RS已满.但是,由于其他原因,可能还有其他uops在RS中等待.因此,我们期望分配器在269周期或之前未充分利用其带宽.通过查看指令的IACA跟踪(11,5),我们可以看到情况发生在第61周期,这比269早得多.这意味着我的预测器非常乐观,或者与其他端口绑定的微量计数也表现出类似的行为.我的胆量告诉我它是后者.但这足以理解为什么IACA已经说过代码是后端绑定的.您可以对第一个代码执行类似的分析,以了解它为什么是前端绑定.我想我只是留给读者练习.

如果IACA不支持特定的代码或者特定的微结构不存在像IACA这样的工具,则可以遵循此手动分析.线性回归模型能够在分配器未充分利用其带宽的迭代次数之后进行估计.例如,在这种情况下,周期269对应于迭代269/11/2 = 269/22 = 12.因此,只要最大迭代次数不大于12,循环的后端性能就会小于问题.

@Bee有一个相关的帖子:x86 uops是如何安排的,确切地说?.

我可以发布前24个周期内发生的细节.

附注:Wikichip关于Skylake的文章中有两个错误.首先,Broadwell的调度程序有60个,而不是64个.其次,分配器的吞吐量最多只有4个融合的uop.


推荐阅读
  • Idontunderstandwhythecommentedanduncommentedlinedontyieldthesameresult(LinuxGCC,wi ... [详细]
  • TunnelWarfareTimeLimit:1000MS MemoryLimit:131072KTotalSubmissions:7307 ... [详细]
  • 电子与正电子的相互作用
    本文探讨了电子与正电子之间的基本物理特性及其在现代物理学中的应用,包括它们的产生、湮灭过程以及在粒子加速器和宇宙射线中的表现。 ... [详细]
  • 正在学习操作系统开发,遇到一个内核在GRUB Legacy(0.97)中无法成功引导的问题。具体表现为输入内核命令后显示错误信息,尝试引导时GRUB挂起。 ... [详细]
  • 本文详细介绍了MySQL表分区的概念、类型及其在实际应用中的实施方法,特别是针对Zabbix数据库的优化策略。 ... [详细]
  • 我们正在使用GNU Make来构建我们的系统,在makefile文件的末尾,我们通过一个名为Makedepends的包含来生成一系列的.d文件。然而,当文件被删除或移动时,依赖关系会中断,我们需要寻找一种方法来优雅地处理这种情况。 ... [详细]
  • DropBlock:一种卷积网络的正则化技术
    本文详细探讨了DropBlock这一正则化方法在卷积神经网络中的应用与效果。通过结构化的dropout方式,即在特征图中连续区域内的单元同时被丢弃,DropBlock有效解决了传统dropout在卷积层应用时效果不佳的问题。更多理论分析及其实现细节可参考原文链接。 ... [详细]
  • 本文将指导你如何通过自定义配置,使 Windows Terminal 中的 PowerShell 7 更加高效且美观。我们将移除默认的广告和提示符,设置快捷键,并添加实用的别名和功能。 ... [详细]
  • 本文介绍了一种算法,用于在一个给定的二叉树中找到一个节点,该节点的子树包含最大数量的值小于该节点的节点。如果存在多个符合条件的节点,可以选择任意一个。 ... [详细]
  • 深入解析 Zend Guard 4 功能与配置
    本文旨在通过图文并茂的方式详细介绍 Zend Guard 4 的核心功能及其配置方法,特别适合英文阅读能力有限的技术人员。文中不仅提供了详细的步骤说明,还附带了实际操作中的注意事项,帮助读者更好地理解和应用这一工具。 ... [详细]
  • C基本语法C程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。对象-对象具有状态和行为 ... [详细]
  • 图神经网络模型综述
    本文综述了图神经网络(Graph Neural Networks, GNN)的发展,从传统的数据存储模型转向图和动态模型,探讨了模型中的显性和隐性结构,并详细介绍了GNN的关键组件及其应用。 ... [详细]
  • PHP 5.4.8 编译安装指南
    本文详细介绍了如何在Linux环境下编译安装PHP 5.4.8,并配置为FastCGI模式运行。包括所需依赖包的安装、源代码下载、编译配置及启动服务等步骤。 ... [详细]
  • Qt应用开发:创建基本窗口
    本文介绍如何使用Qt框架创建基础窗口的两种方法。第一种方法直接在main函数中创建并显示窗口;第二种方法通过定义一个继承自QWidget的类来实现更复杂的功能。 ... [详细]
  • 本文章利用header()函数来实现页面跳,我们介绍到404,302,301等状态跳转哦,下面有很多的状态自定的函数有需要的同学可以测试一下。heade ... [详细]
author-avatar
Andiry舍甫琴科
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有