- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用Intel® Architecture Code Analyzer(IACA)发现了一些意外(对我而言)。
以下指令使用[base+index]
寻址
addps xmm1, xmmword ptr [rsi+rax*1]
[base+offset]
addps xmm1, xmmword ptr [rsi]
FADD DOUBLE PTR [RDI + RSI*8]
[base+index]
寻址进行微操作融合的示例。参见,例如,第12.2节“Core2上的相同示例”。那么正确的答案是什么?
最佳答案
在解码器和uop缓存中,寻址模式不会影响微融合(除非带有立即数的指令不能对与RIP相关的寻址模式进行微融合)。
但是uop和寻址模式的某些组合无法在ROB中保持微融合(在乱序内核中),因此,英特尔SnB系列CPU在必要时(在问题/重命名阶段。对于问题吞吐量和无序窗口大小(ROB大小),重要的是取消分层后的融合域uop计数。
Intel's optimization manual在第2.5.2.4节:Micro-op队列和环路流检测器(LSD)中描述了Sandybridge的取消分层,但未描述任何后续的微体系结构的更改。
更新:现在,英特尔手册中有详细的部分描述了Haswell的分层。请参阅第2.4.5节“分层”。在2.5.2.4节中对SandyBridge进行了简要说明。
规则,据我从SnB,HSW和SKL的实验中可以看出来的最好:
adc
和cmov
不会微熔断。大多数VEX编码的指令也不会融合,因为它们通常具有三个操作数(因此paddb xmm0, [rdi+rbx]
融合而vpaddb xmm0, xmm0, [rdi+rbx]
不融合)。最后,偶尔的第2个操作数只写的操作数指令(例如pabsb xmm0, [rax + rbx]
)也不会融合。 IACA应用SnB规则是错误的。 dst+(initial_src-initial_dst)
来寻址src。然后,您只需要在循环内增加dst寄存器。)
shufps xmm, [mem], imm8
或
vinsertf128 ymm, ymm, [mem], imm8
在通过Skylake的SnB上始终为2 uops,即使其寄存器源版本仅为1 uop。这对于带有imm8控制操作数加上通常的dest / src1,src2寄存器/内存操作数的指令来说是典型的,但是还有其他几种情况。例如
PSRLW/D/Q xmm,[mem]
(来自内存操作数的 vector 移位计数)没有微熔丝,PMULLD也没有。
# store
mov [rax], edi SnB/HSW/SKL: 1 fused-domain, 2 unfused. The store-address uop can run on port7.
mov [rax+rsi], edi SnB: unlaminated. HSW/SKL: stays micro-fused. (The store-address can't use port7, though).
mov [buf +rax*4], edi SnB: unlaminated. HSW/SKL: stays micro-fused.
# normal ALU stuff
add edx, [rsp+rsi] SnB: unlaminated. HSW/SKL: stays micro-fused.
# I assume the majority of traditional/normal ALU insns are like add
HSW / SKL可能必须取消层压的三输入指令
vfmadd213ps xmm0,xmm0,[rel buf] HSW/SKL: stays micro-fused: 1 fused, 2 unfused.
vfmadd213ps xmm0,xmm0,[rdi] HSW/SKL: stays micro-fused
vfmadd213ps xmm0,xmm0,[0+rdi*4] HSW/SKL: un-laminated: 2 uops in fused & unfused-domains.
(So indexed addressing mode is still the condition for HSW/SKL, same as documented by Intel for SnB)
# no idea why this one-source BMI2 instruction is unlaminated
# It's different from ADD in that its destination is write-only (and it uses a VEX encoding)
blsi edi, [rdi] HSW/SKL: 1 fused-domain, 2 unfused.
blsi edi, [rdi+rsi] HSW/SKL: 2 fused & unfused-domain.
adc eax, [rdi] same as cmov r, [rdi]
cmove ebx, [rdi] Stays micro-fused. (SnB?)/HSW: 2 fused-domain, 3 unfused domain.
SKL: 1 fused-domain, 2 unfused.
# I haven't confirmed that this micro-fuses in the decoders, but I'm assuming it does since a one-register addressing mode does.
adc eax, [rdi+rsi] same as cmov r, [rdi+rsi]
cmove ebx, [rdi+rax] SnB: untested, probably 3 fused&unfused-domain.
HSW: un-laminated to 3 fused&unfused-domain.
SKL: un-laminated to 2 fused&unfused-domain.
我认为Broadwell的行为类似于Skylake的ADC / cmov。
cmovcc r,m
和
adc r,m
根本没有微熔丝,但这与我的实验不符。我正在测量的周期计数与融合域uop发行计数匹配,出现了4 uops /时钟的发行瓶颈。希望他会再次检查并更正表格。
add [rdi], eax SnB: untested (Agner says 2 fused-domain, 4 unfused-domain (load + ALU + store-address + store-data)
HSW/SKL: 2 fused-domain, 4 unfused.
add [rdi+rsi], eax SnB: untested, probably 4 fused & unfused-domain
HSW/SKL: 3 fused-domain, 4 unfused. (I don't know which uop stays fused).
HSW: About 0.95 cycles extra store-forwarding latency vs. [rdi] for the same address used repeatedly. (6.98c per iter, up from 6.04c for [rdi])
SKL: 0.02c extra latency (5.45c per iter, up from 5.43c for [rdi]), again in a tiny loop with dec ecx/jnz
adc [rdi], eax SnB: untested
HSW: 4 fused-domain, 6 unfused-domain. (same-address throughput 7.23c with dec, 7.19c with sub ecx,1)
SKL: 4 fused-domain, 6 unfused-domain. (same-address throughput ~5.25c with dec, 5.28c with sub)
adc [rdi+rsi], eax SnB: untested
HSW: 5 fused-domain, 6 unfused-domain. (same-address throughput = 7.03c)
SKL: 5 fused-domain, 6 unfused-domain. (same-address throughput = ~5.4c with sub ecx,1 for the loop branch, or 5.23c with dec ecx for the loop branch.)
是的,没错,
adc [rdi],eax
/
dec ecx
/
jnz
的运行速度比SKL上的
add
而不是
adc
的循环快。我没有尝试使用其他地址,因为显然SKL不喜欢重复重写同一地址(存储转发延迟比预期的高。另请参见
this post about repeated store/reload to the same address being slower than expected on SKL。
adc
太多了,因为Intel P6系列(显然是SnB系列)不能为多uup指令的所有uo保持相同的TLB条目,所以
needs an extra uop to work around the problem-case where the load and add complete, and then the store faults, but the insn can't just be restarted because CF has already been updated。来自Andy Glew(@krazyglew)的一系列有趣的评论。
adc [base+idx], reg
的一条指令中产生了4个以上的融合域uops。
add
和
adc
是否充分利用了这一点,还是不确定英特尔是否必须通过一些说明使Haswell脱颖而出
vpgatherdd
的一些注释比
pinsrw
循环多大约1.7倍。)
ocperf.py
在SKL上的Linux 4.10和HSW上的Linux 4.8上运行了相同的静态二进制文件。 (HSW便携式计算机NFS安装在我的SKL桌面的/ home上。)
perf
命令一起使用。 (遗憾的是,标准
perf
没有针对大多数特定于硬件的PMU事件(例如uops)的符号名称。)我在
recent answer中使用了它。
ocperf.py
provides symbolic names for these uarch-specific PMU events,因此您不必查找表。同样,相同的符号名称可跨多个架构使用。当我第一次写这个答案时,我并不知道。
nop
,它们仍然位于uop缓存中,并且与其他任何uop一样,都通过管道进行传递,只是它们没有被调度到执行端口。 (
xor x, same
或消除的 Action 将是相同的。)
yasm -f elf64 uop-test.s && ld uop-test.o -o uop-test
GLOBAL _start
_start:
xor eax, eax
xor ebx, ebx
xor edx, edx
xor edi, edi
lea rsi, [rel mydata] ; load pointer
mov ecx, 10000000
cmp dword [rsp], 2 ; argc >= 2
jge .loop_2reg
ALIGN 32
.loop_1reg:
or eax, [rsi + 0]
or ebx, [rsi + 4]
dec ecx
nop
nop
nop
nop
jg .loop_1reg
; xchg r8, r9 ; no effect on flags; decided to use NOPs instead
jmp .out
ALIGN 32
.loop_2reg:
or eax, [rsi + 0 + rdi]
or ebx, [rsi + 4 + rdi]
dec ecx
nop
nop
nop
nop
jg .loop_2reg
.out:
xor edi, edi
mov eax, 231 ; exit(0)
syscall
SECTION .rodata
mydata:
db 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
我还发现,如果循环不是4微秒的倍数,则循环缓冲区外的uop带宽不是恒定的4。 (即
abc
,
abc
,...;不是
abca
,
bcab
,...)。不幸的是,Agner Fog的microarch文档尚不清楚循环缓冲区的这一限制。有关HSW / SKL的更多调查,请参见
Is performance reduced when executing loops whose uop count is not a multiple of processor width?。在这种情况下,SnB可能比HSW差,但是我不确定,并且仍然没有可用的SnB硬件。
nop
和分支之间使用了
dec
。我使用了4个
nop
,所以使用微融合时,循环将为8微码,并且每1次迭代以2个周期填充管道。
$ perf stat -e task-clock,cycles,instructions,r1b1,r10e,r2c2,r1c2,stalled-cycles-frontend,stalled-cycles-backend ./uop-test
Performance counter stats for './uop-test':
11.489620 task-clock (msec) # 0.961 CPUs utilized
20,288,530 cycles # 1.766 GHz
80,082,993 instructions # 3.95 insns per cycle
# 0.00 stalled cycles per insn
60,190,182 r1b1 ; UOPS_DISPATCHED: (unfused-domain. 1->umask 02 -> uops sent to execution ports from this thread)
80,203,853 r10e ; UOPS_ISSUED: fused-domain
80,118,315 r2c2 ; UOPS_RETIRED: retirement slots used (fused-domain)
100,136,097 r1c2 ; UOPS_RETIRED: ALL (unfused-domain)
220,440 stalled-cycles-frontend # 1.09% frontend cycles idle
193,887 stalled-cycles-backend # 0.96% backend cycles idle
0.011949917 seconds time elapsed
测试2-reg寻址模式:使用cmdline arg
$ perf stat -e task-clock,cycles,instructions,r1b1,r10e,r2c2,r1c2,stalled-cycles-frontend,stalled-cycles-backend ./uop-test x
Performance counter stats for './uop-test x':
18.756134 task-clock (msec) # 0.981 CPUs utilized
30,377,306 cycles # 1.620 GHz
80,105,553 instructions # 2.64 insns per cycle
# 0.01 stalled cycles per insn
60,218,693 r1b1 ; UOPS_DISPATCHED: (unfused-domain. 1->umask 02 -> uops sent to execution ports from this thread)
100,224,654 r10e ; UOPS_ISSUED: fused-domain
100,148,591 r2c2 ; UOPS_RETIRED: retirement slots used (fused-domain)
100,172,151 r1c2 ; UOPS_RETIRED: ALL (unfused-domain)
307,712 stalled-cycles-frontend # 1.01% frontend cycles idle
1,100,168 stalled-cycles-backend # 3.62% backend cycles idle
0.019114911 seconds time elapsed
因此,两个版本都运行8000万条指令,并向执行端口分派(dispatch)了60M指令。 (带有内存源的
or
会为
or
调度到ALU,并为加载分配一个加载端口,无论它是否在管道的其余部分中进行了微融合。
nop
根本不会调度到执行端口。)同样,这两个版本都将退回100M未融合域的uops,因为这里有40M的nops计数。
[base + immediate offset]
寻址一起使用)而不是使用
[base + index]
寻址模式来实现,则在循环中进行大量内存引用的代码可能会更快。
cmp dword [abs mydata], 0x1b ; fused counters != unfused counters (micro-fusion happened, and wasn't un-laminated). Uses 2 entries in the uop-cache, according to Agner Fog's testing
cmp dword [rel mydata], 0x1b ; fused counters ~= unfused counters (micro-fusion didn't happen)
当没有即时消息时,RIP-rel会进行微熔断(并保持熔断),例如:
or eax, dword [rel mydata] ; fused counters != unfused counters, i.e. micro-fusion happens
ALIGN 32
.dep_fuse:
or eax, [rsi + 0]
or eax, [rsi + 0]
or eax, [rsi + 0]
or eax, [rsi + 0]
or eax, [rsi + 0]
dec ecx
jg .dep_fuse
由于
eax
dep链,此循环每次迭代以5个周期运行。不比
or eax, [rsi + 0 + rdi]
或
mov ebx, [rsi + 0 + rdi] / or eax, ebx
序列快。 (未融合版本和
mov
版本都运行相同数量的uops。)调度/ dep检查在未融合域中进行。新发行的微指令进入调度程序(又称为预留站(RS))以及ROB。他们在调度后离开调度程序(又被发送到执行单元),但留在ROB中直到退休。因此,用于隐藏负载延迟的无序窗口至少是调度程序的大小(在Skylake中为
54 unfused-domain uops in Sandybridge, 60 in Haswell,为97)。
or eax, [mydata + rdi+4*rdi]
的循环(其中rdi为零)运行的次数和周期与带有
or eax, [rsi+rdi]
的循环一样多。此寻址模式可用于迭代从固定地址开始的奇数大小的结构数组。这可能在大多数程序中从未使用过,因此毫不奇怪,英特尔没有花费晶体管来允许这种特殊情况下的2寄存器模式进行微熔丝。 (而且无论如何,在需要寄存器和比例因子的情况下,英特尔将其记录为“索引寻址模式”。)
cmp
/
jcc
或
dec
/
jcc
的宏融合创建了一个uop,即使在未融合域中也保持为单个uop。
dec / nop / jge
仍然可以在单个周期中运行,但是只有三个,而不是一个。
关于assembly - 微融合和寻址模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26046634/
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
使用微 Controller 时,通常您必须对寄存器进行写入和读取,为了使代码更具可读性,您需要定义寄存器地址及其位。这有点好,但是当您的寄存器名称彼此非常相似时,它很快就会变得困惑,例如此处所示 #
微 Controller 背景下的“原子操作”是什么? 我正在研究 TI F28027 MCU。 The data sheet says that its operations are atomic
我正在用 PIC 微 Controller 做一个项目。我有一个 ADC 采样并将数据保存到 RAM 存储器,一旦 RAM 被填满,我需要使用 PIC 微 Controller 通过蓝牙发送它。 我的
如何确定微 Controller 中特定程序所需的堆栈内存? 例如,假设我有一个内部可能有许多子例程或线程的程序。在我开始执行程序之前,我想修复这个程序的堆栈大小。我如何标记堆栈的终点。 最佳答案 我
我知道 printf 和 sprintf 之间的基本功能差异。但是,我想知道它们之间一些与时间/延迟相关的差异。显然,我想在我的一个自定义构建 RTOS 的任务中使用它。你怎么看 ?我想知道更多它会如
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 5 年前。
我有一个一般性的问题。我在微 Controller 上记录错误。但是微 Controller 的资源比 Windows 计算机更有限。在我的例子中,我将 64 个错误代码保存在一个队列中,由 Free
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 6 年前。 Improve th
假设我有一个时钟速度为 20 Mhz 的 8 位定时器。计时器在多少时间内可以计数多远而不溢出。或者1秒内溢出多少次?我知道它可以数到 255 并且会溢出 最佳答案 时间和频率之间的关系是t = 1/
我正在开展一个全面的长期 C 编程项目,该项目需要模块化编程方法。作为设计的一部分,将创建库,因此我想确认头文件组织的正确/错误解释: 问题 假设您正在创建一个库。经过深思熟虑,您决定您希望构想的最终
1. #define timers ((dual_timers *)0x03FF6000) 这是 ARM 微 Controller 中使用的内存映射定义 结构定义在哪里 2. struct dua
我购买了 LinkSprite JPEG 彩色相机和 LPC1768 mbed 微 Controller 。通过“LinkSprite”相机,我可以拍摄 jpeg 格式的图像,根据他们提供的教程,我可
我有很多不同的时间来跟踪我的设计,但没有什么是 super 关键的。 10 毫秒 +/- 几毫秒根本不是什么大问题。但是可能有 10 个不同的定时器同时在不同的周期进行计数,显然我没有足够的专用定时器
是否可以通过串行端口与 PIC 单片机通信 Android 应用程序?我可以使用哪些低成本手机?对不起,我是哥伦比亚人。 最佳答案 不确定 PIC,但是 Arduino可能是一个很好的引用点,并且有一
今天我一直在思考以下问题: 在一台普通的 pc 中,当你分配一些内存时,你向操作系统请求它,它会跟踪哪些内存段被占用,哪些内存段没有被占用,并且不要让你弄乱其他程序的内存等。但是微 Controlle
我已经为微 Controller 的键盘开发了一个 c 驱动程序。我想改变它,例如,当我按下 1 时,它会显示 1,直到我按下另一个数字。截至目前,数字只有在我按下数字时才会改变,这意味着一旦我松开键
我有一个在线程之间共享的 volatile unsigned char array LedState[5] 变量。数组中的每个索引表示一个状态。根据每个状态,LED 将以不同的顺序闪烁。一个线程设置数
我有一个项目要对微 Controller PIC18F 进行编程,我必须将一个开关电路连接到微 Controller 板上,这个开关电路有一个电锁和一个蜂鸣器要连接到它。 锁最初是通电的。假设当我发送
我是一名优秀的程序员,十分优秀!