32 位和 64 位寄存器是否会导致 CPU 微架构的差异?
Do 32-bit and 64-bit registers cause differences in CPU micro architecture?
我正在尝试将 Peter Cordes 在 中提到的方法与 'set all bits in CPU register to 1'.
的问题进行比较
因此,我编写了一个基准测试,将所有 13 个寄存器设置为所有位 1,除了 e/rsp
、e/rbp
和 e/rcx
。
代码如下。 times 32 nop
用于避免DSB和LSD影响
mov ecx, 100000000
Align 32
.test3:
times 32 nop
mov rax,-1
mov rbx,-1
;mov ecx,-1
mov rdx,-1
mov rdi,-1
mov rsi,-1
mov r8,-1
mov r9,-1
mov r10,-1
mov r11,-1
mov r12,-1
mov r13,-1
mov r14,-1
mov r15,-1
dec ecx
jge .test3
jmp .out
我测试了他提到的以下方法,Full code in here
mov e/rax, -1
xor eax, eax
dec e/rax
xor ecx, ecx
lea e/rax, [rcx-1]
or e/rax, -1
为了让这个问题更简洁,我会用group1 a (g1a)
代替下面table中的mov eax,-1
。
number
pattern
test number
group1 a
mov eax,-1
test 7
group1 b
mov rax,-1
test3
group2 a
xor eax, eax / dec eax
test6
group2 b
xor eax, eax / dec rax
test2
group3 a
xor ecx, ecx / lea eax, [rcx-1]
test0
group3 b
xor ecx, ecx / lea rax, [rcx-1]
test-1(test00)
group4 a
or eax,-1
test5
group4 b
or rax,-1
test1
下面的table表示从第1组到第3组,使用64位寄存器时,每循环多1个周期。
IDQ_UOPS_NOT_DELIVERED也增加了,这或许可以解释循环次数增加的原因。 但这能解释每个循环多 1 个循环吗?
cycles
MITE cycles(r1002479)
MITE 4uops cycles (r4002479)
IDQ UOPS NOT DELIVERED(r19c)
g1a
1,300,903,705
1,300,104,496
800,055,137
601,487,115
g1b
1,400,852,931
1,400,092,325
800,049,313
1,001,524,712
g2a
1,600,920,156
1,600,113,480
1,300,061,359
501,522,554
g2b
1,700,834,769
1,700,108,688
1,300,057,576
901,467,008
g3a
1,701,971,425
1,700,093,298
1,300,111,482
902,327,493
g3b
1,800,891,861
1,800,110,096
1,300,059,338
1,301,497,001
g4a
1,201,164,208
1,200,122,275
1,100,049,081
201,592,292
g4b
1,200,553,577
1,200,074,422
1,100,031,729
200,772,985
另外,g2a和g2b的端口分布不同,不像g1a和g1b(g1a和g1b的端口分布一样),或者g3a和g3b
如果我评论times 32 nop
,这种现象就消失了。与MITE有关吗?
p0
p1
p2
p3
p4
p5
p6
p7
g1a
299,868,019
300,014,657
5,925
7,794
16,589
300,279,232
499,885,294
7,242
g1b
299,935,968
300,085,089
6,622
8,758
18,842
299,935,445
500,426,436
7,336
g2a
299,800,192
299,758,460
7,461
9,635
20,622
399,836,486
400,312,354
8,446
g2b
200,047,079
200,203,026
7,899
9,967
21,539
500,542,313
500,296,034
9,635
g3a
36,568
550,860,773
7,784
10,147
22,538
749,063,082
99,856,623
9,767
g3b
36,858
599,960,197
8,232
10,763
23,086
700,499,893
100,078,368
9,513
g4a
200,142,036
300,600,535
5,383
6,705
15,344
400,045,302
500,364,377
6,802
g4b
200,224,703
300,284,609
5,464
7,031
15,817
400,047,050
499,467,546
6,746
环境:英特尔 i7-10700、ubuntu 20.04 和 NASM 2.14.02。
我用英语解释这个有点困难。描述不清楚的请留言
所有示例中的瓶颈都是预解码器。
我用我的模拟器 uiCA (https://uica.uops.info/, https://github.com/andreas-abel/uiCA) 分析了你的例子。它预测以下吞吐量,与您的测量值非常匹配:
TP
Link
g1a
13.00
https://uica.uops.info/?code=...
g1b
14.00
https://uica.uops.info/?code=...
g2a
16.00
https://uica.uops.info/?code=...
g2b
17.00
https://uica.uops.info/?code=...
g3a
17.00
https://uica.uops.info/?code=...
g3b
18.00
https://uica.uops.info/?code=...
g4a
12.00
https://uica.uops.info/?code=...
g4b
12.00
https://uica.uops.info/?code=...
uiCA 生成的跟踪 table 提供了一些代码执行方式的见解。例如,对于 g1a,它生成以下跟踪:
你可以看到对于32个nop,预解码器需要8个周期,而对于剩余的指令,它需要5个周期,它们一起对应于你测量的13个周期。
您可能会注意到,在某些周期中,只有少量指令被预解码;例如,在第四个周期,只有一条指令被预解码。这是因为预解码器在对齐的 16 字节块上工作,并且它每个周期最多可以处理 5 条指令(请注意,某些来源错误地声称它每个周期可以处理 6 条指令)。您可以在 this paper.
中找到有关预解码器的更多详细信息,例如它如何处理跨越 16 字节边界的指令
如果将此轨迹与 g1b 的轨迹进行比较,
你可以看到nops之后的指令现在需要6个而不是5个周期来预解码,这是因为g1b中的几个指令比g1a中相应的指令长
我正在尝试将 Peter Cordes 在
因此,我编写了一个基准测试,将所有 13 个寄存器设置为所有位 1,除了 e/rsp
、e/rbp
和 e/rcx
。
代码如下。 times 32 nop
用于避免DSB和LSD影响
mov ecx, 100000000
Align 32
.test3:
times 32 nop
mov rax,-1
mov rbx,-1
;mov ecx,-1
mov rdx,-1
mov rdi,-1
mov rsi,-1
mov r8,-1
mov r9,-1
mov r10,-1
mov r11,-1
mov r12,-1
mov r13,-1
mov r14,-1
mov r15,-1
dec ecx
jge .test3
jmp .out
我测试了他提到的以下方法,Full code in here
mov e/rax, -1
xor eax, eax
dec e/rax
xor ecx, ecx
lea e/rax, [rcx-1]
or e/rax, -1
为了让这个问题更简洁,我会用group1 a (g1a)
代替下面table中的mov eax,-1
。
number | pattern | test number |
---|---|---|
group1 a | mov eax,-1 | test 7 |
group1 b | mov rax,-1 | test3 |
group2 a | xor eax, eax / dec eax | test6 |
group2 b | xor eax, eax / dec rax | test2 |
group3 a | xor ecx, ecx / lea eax, [rcx-1] | test0 |
group3 b | xor ecx, ecx / lea rax, [rcx-1] | test-1(test00) |
group4 a | or eax,-1 | test5 |
group4 b | or rax,-1 | test1 |
下面的table表示从第1组到第3组,使用64位寄存器时,每循环多1个周期。
IDQ_UOPS_NOT_DELIVERED也增加了,这或许可以解释循环次数增加的原因。 但这能解释每个循环多 1 个循环吗?
cycles | MITE cycles(r1002479) | MITE 4uops cycles (r4002479) | IDQ UOPS NOT DELIVERED(r19c) | |
---|---|---|---|---|
g1a | 1,300,903,705 | 1,300,104,496 | 800,055,137 | 601,487,115 |
g1b | 1,400,852,931 | 1,400,092,325 | 800,049,313 | 1,001,524,712 |
g2a | 1,600,920,156 | 1,600,113,480 | 1,300,061,359 | 501,522,554 |
g2b | 1,700,834,769 | 1,700,108,688 | 1,300,057,576 | 901,467,008 |
g3a | 1,701,971,425 | 1,700,093,298 | 1,300,111,482 | 902,327,493 |
g3b | 1,800,891,861 | 1,800,110,096 | 1,300,059,338 | 1,301,497,001 |
g4a | 1,201,164,208 | 1,200,122,275 | 1,100,049,081 | 201,592,292 |
g4b | 1,200,553,577 | 1,200,074,422 | 1,100,031,729 | 200,772,985 |
另外,g2a和g2b的端口分布不同,不像g1a和g1b(g1a和g1b的端口分布一样),或者g3a和g3b
如果我评论times 32 nop
,这种现象就消失了。与MITE有关吗?
p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7 | |
---|---|---|---|---|---|---|---|---|
g1a | 299,868,019 | 300,014,657 | 5,925 | 7,794 | 16,589 | 300,279,232 | 499,885,294 | 7,242 |
g1b | 299,935,968 | 300,085,089 | 6,622 | 8,758 | 18,842 | 299,935,445 | 500,426,436 | 7,336 |
g2a | 299,800,192 | 299,758,460 | 7,461 | 9,635 | 20,622 | 399,836,486 | 400,312,354 | 8,446 |
g2b | 200,047,079 | 200,203,026 | 7,899 | 9,967 | 21,539 | 500,542,313 | 500,296,034 | 9,635 |
g3a | 36,568 | 550,860,773 | 7,784 | 10,147 | 22,538 | 749,063,082 | 99,856,623 | 9,767 |
g3b | 36,858 | 599,960,197 | 8,232 | 10,763 | 23,086 | 700,499,893 | 100,078,368 | 9,513 |
g4a | 200,142,036 | 300,600,535 | 5,383 | 6,705 | 15,344 | 400,045,302 | 500,364,377 | 6,802 |
g4b | 200,224,703 | 300,284,609 | 5,464 | 7,031 | 15,817 | 400,047,050 | 499,467,546 | 6,746 |
环境:英特尔 i7-10700、ubuntu 20.04 和 NASM 2.14.02。
我用英语解释这个有点困难。描述不清楚的请留言
所有示例中的瓶颈都是预解码器。
我用我的模拟器 uiCA (https://uica.uops.info/, https://github.com/andreas-abel/uiCA) 分析了你的例子。它预测以下吞吐量,与您的测量值非常匹配:
TP | Link | |
---|---|---|
g1a | 13.00 | https://uica.uops.info/?code=... |
g1b | 14.00 | https://uica.uops.info/?code=... |
g2a | 16.00 | https://uica.uops.info/?code=... |
g2b | 17.00 | https://uica.uops.info/?code=... |
g3a | 17.00 | https://uica.uops.info/?code=... |
g3b | 18.00 | https://uica.uops.info/?code=... |
g4a | 12.00 | https://uica.uops.info/?code=... |
g4b | 12.00 | https://uica.uops.info/?code=... |
uiCA 生成的跟踪 table 提供了一些代码执行方式的见解。例如,对于 g1a,它生成以下跟踪:
你可以看到对于32个nop,预解码器需要8个周期,而对于剩余的指令,它需要5个周期,它们一起对应于你测量的13个周期。
您可能会注意到,在某些周期中,只有少量指令被预解码;例如,在第四个周期,只有一条指令被预解码。这是因为预解码器在对齐的 16 字节块上工作,并且它每个周期最多可以处理 5 条指令(请注意,某些来源错误地声称它每个周期可以处理 6 条指令)。您可以在 this paper.
中找到有关预解码器的更多详细信息,例如它如何处理跨越 16 字节边界的指令如果将此轨迹与 g1b 的轨迹进行比较,