关于掩码寄存器

AVX-512指令集包括八个所谓的掩码寄存器[1]-从k0 [2]到k7。它们适合与大多数ALU操作一起使用,并允许您对矢量元素执行掩码操作,以对目标寄存器中的数据进行归零或合并[3],从而加快了代码的执行速度,这将需要在AVX2指令集和早期版本中进行其他合并操作。

如果以上内容不足以使您成为掩码寄存器狂热者的追随者,我将引用维基百科的文章摘录,希望文章最终可以帮助您解决:
大多数AVX-512命令可以使用与8个掩码寄存器(k0 – k7)之一相对应的操作数掩码。如果将掩码寄存器用作操作掩码,则k0寄存器的行为与其余掩码寄存器不同:在这种情况下,它充当硬编码常量,指示此操作未应用掩码。但是,在算术和逻辑运算中以及将值写入掩码寄存器时,k0的行为类似于正常的工作寄存器。在大多数命令中,掩码寄存器用作确定应该将哪些项目写入输出寄存器的掩码。操作数掩码的行为取决于标志:如果设置了该标志,则所有未选择的元素都将被重置(“归零”模式,),如果没有,则所有未选择的元素都保持其先前状态(合并模式,merge)。合并模式与混合指令具有相同的效果

通常,掩码寄存器[4]是一项重要的创新,但是与通用寄存器(eaxrsi等)或SIMD寄存器(xmm0ymm5等)相比,它们很少被记住在英特尔演示文稿中显示了微体系结构资源的大小,未提及掩码寄存器:

图片

据我所知,关于掩码寄存器的物理寄存器文件(物理寄存器文件,PRF的大小的信息也从未发布过。现在我们将修复它。
我使用工具的修改版来测量命令重排序缓冲区(ROB大小,大小由Henry Wong [5](以下简称为Henry)创建和描述。他使用此工具计算了先前体系结构中非常规执行的已记录和未记录结构的大小。如果您还没有阅读亨利的笔记,请停下来再返回。我的文章将等待。

好吧,读?出于危害,这是亨利(Henry)文章的摘要:

ROB


许多镇流器指令插入到两个读取指令之间,并发生高速缓存未命中[6] -它们的确切数量将取决于我们要测量的处理器资源。如果没有太多镇流器命令,则将并行处理两个缓存未命中,因此它们的延迟将重叠,总执行时间将约为一个缓存未命中所需的[7]倍。

但是,如果镇流器命令的数量超过某个临界阈值,则相应的资源将被完全耗尽,并且在发出具有缓存未命中的第二条命令之前,将停止在ROB中放置团队。在这种情况下,它们的并行处理将是不可能的,并且总时间将几乎是一次此类操作的时间的两倍,这将在图表中反映为急剧跳跃。

最后,编写测试,以便团队仅使用要测试的资源的一个单位-在这种情况下,图上的峰峰值将指示其总体积。因此,通常,标准通用命令使用通用PRF寄存器中的一个物理寄存器,因此非常适合测量给定资源的数量。

掩码寄存器的物理寄存器文件的大小


在此测试中,我们将执行将值写入掩码寄存器的命令,以找出这些寄存器的PRF大小。

让我们从一系列kaddd k1,k2,k3团队开始(显示16个镇流器团队):

mov    rcx,QWORD PTR [rcx]  ;    -
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
kaddd  k1,k2,k3
mov    rdx,QWORD PTR [rdx]  ;    -
lfence                      ;      ,    
                            ;   
;     16 

每个kaddd命令消耗一个物理掩码寄存器。如果镇流器命令的数量小于或等于掩码寄存器的数量,则将在并行模式下处理高速缓存未中,否则在顺序模式下进行。因此,当从并行模式切换到串行模式时,我们应该在图形上看到一个急剧的跳跃,这表明执行时间增加了。

这正是我们正在观察的结果:

图片

让我们仔细看一下上升情况:

图片

正如我们现在所看到的,跳跃并不那么剧烈:随着镇流器命令的数量从130增加到134,执行速度在最小和最大级别之间取中间值。亨利称这种行为不完美;我在许多测试中都观察到了它,尽管不是全部。事实是,硬件的实现并不能总是在资源接近极限时完全耗尽它[8]-在某些情况下可以成功,而在另一些情况下只有很少的团队达到理论上的最大值。
在这方面,我们对倒数第二个上升点感兴趣,在该倒数第二个上升点,速度仍然高于慢速模式。这一点表明我们可用的资源单元数,这意味着至少有尽可能多的物理寄存器。如您所见,在这种情况下约为134.

因此,SKX 具有134个物理寄存器,能够存储掩码寄存器的推测性(通过预期执行获得)值亨利(Henry)建议再使用8个来存储八个掩码寄存器的当前体系结构状态,因此它们的PRF总量可以估计为142。这比通用寄存器(180)和SIMD寄存器(168)的文件大小略小,但仍然很多(请参见其他平台的非常规执行资源的大小表)。

假设此文件足够大,以至于在实践中我们没有时间完全占用它:很难想象真实的代码中几乎60%的命令[9]会写[10]来屏蔽寄存器-即,因此将需要许多资源来耗尽此资源。

这些注册表文件是否不同?


您必须已经注意到,到目前为止,我默认情况下假设掩码寄存器PRF是一个单独的文件,不会与其他类型的寄存器文件相交。基于掩码寄存器的工作原理以及它们是寄存器重命名的单独域的一部分,我相信这很有可能[11]。支持我的假设的另一个论据是,观察到的PRF掩码寄存器的大小与通用寄存器文件或SIMD寄存器文件的大小不匹配。实际上,我们可以通过测试来进行测试!

此测试与之前的测试类似,但现在为kaddd命令将与使用通用寄存器或SIMD寄存器的命令交替显示。如果将掩码寄存器与同一寄存器文件中的第一个或第二个寄存器组合在一起,则图中的跳转应指示相应的PRF的大小。如果未合并寄存器文件,我们将遇到其他限制,该限制将不等于两个寄存器文件中的任何一个的大小,但将等于例如ROB的大小。

测试29中kaddd命令和标量添加命令交替出现

mov    rcx,QWORD PTR [rcx]
add    ebx,ebx
kaddd  k1,k2,k3
add    esi,esi
kaddd  k1,k2,k3
add    ebx,ebx
kaddd  k1,k2,k3
add    esi,esi
kaddd  k1,k2,k3
add    ebx,ebx
kaddd  k1,k2,k3
add    esi,esi
kaddd  k1,k2,k3
add    ebx,ebx
kaddd  k1,k2,k3
mov    rdx,QWORD PTR [rdx]
lfence

我们看一下图表:

图片

如您所见,占峰值的镇流器数量大于PRF通用寄存器和掩码寄存器的大小。由此得出的结论是,掩码寄存器不包含在通用寄存器文件中。

那么也许它们包含在SIMD寄存器文件中?毕竟,与通用命令相比,掩码寄存器与SIMD命令的关联更大。

要了解,我们将使用测试35,这与这里的差相同试验29 kaddd命令交替与vxorps命令

mov    rcx,QWORD PTR [rcx]
vxorps ymm0,ymm0,ymm1
kaddd  k1,k2,k3
vxorps ymm2,ymm2,ymm3
kaddd  k1,k2,k3
vxorps ymm4,ymm4,ymm5
kaddd  k1,k2,k3
vxorps ymm6,ymm6,ymm7
kaddd  k1,k2,k3
vxorps ymm0,ymm0,ymm1
kaddd  k1,k2,k3
vxorps ymm2,ymm2,ymm3
kaddd  k1,k2,k3
vxorps ymm4,ymm4,ymm5
kaddd  k1,k2,k3
mov    rdx,QWORD PTR [rdx]
lfence

图:

图片

在此测试中,观察到的行为与上一个行为相同,因此我们得出结论,掩码寄存器和SIMD寄存器的寄存器文件也分开了。

未解之谜


但是,在这两个测试中,峰值的末尾都落在大约212个命令上,而该微体系结构的ROB大小为224。也许这只是我们之前已经观察到不完美行为?好吧,让我们检查一下:将这两个测试的结果与测试4的结果进行比较,在测试4中,只有nop命令用作镇流器命令:除了ROB之外,它们不应消耗任何其他资源。比较测试4(nop)和测试29(kaddd和标量加法交替的图形

图片

测试4中慢速模式的开始恰好落在224标志(矢量图像,因此您可以增加它们并自己查看)。结果是212(从这一点开始,慢速模式在将掩码寄存器与通用寄存器或SIMD寄存器交替使用时开始)–这是某些其他资源的限制。实际上,即使交替使用通用寄存器和SIMD寄存器,我们也遇到相同的限制-比较测试4和测试21(它结合了通用寄存器和SIMD vxorps命令的添加):

图片

在您的文章中,标题相同(“未解之谜”)的亨利描述了相同的效果,但更为明显:
, AVS SSE Sandy Bridge 147 , ROB. (, , AVX- , NOP-), , SSE/AVX, , - , 147, – , .
有关详细信息,请参考Henry的文章。我们观察到了类似的效果,但效果并不明显:我们至少设法占据了ROB体积的95%,但我们仍然没有完全耗尽它。也许那个神秘的通用寄存器池与它们的释放机制相关联,例如PRRT表[12],该表跟踪命令完成后可用于释放的寄存器。

最后,让我们讨论屏蔽寄存器的更多功能,并检查通用寄存器和SIMD寄存器可用的优化机制是否适用于它们。

复制副本


对于通用或SIMD命令,可以应用所谓的消除移动。通过这种优化,寄存器重命名机制不允许执行将值从一个寄存器复制到另一个寄存器的命令,例如mov eaxedxvmovdqu ymm1ymm2-而是目标寄存器“简单地” [13]重新分配给RAT中的源寄存器,这使您无需参与ALU就可以做到。

检查副本替换是否适用于kmov k1k2命令。首先,看一下测试28的图形,其中kmovd k1是镇流器组k2
图片
该图看起来与之前使用kaddd命令讨论的测试27 完全相同因此,可以合理地假设填充的是物理寄存器,除非我们在替换副本时不小心耗尽了一些其他资源,它们的行为相同且大小相同[14]。

我们在uops.info网站上找到了更多确认信息:它说掩码寄存器之间kmov copy 命令的所有变体都占用一个在端口p0上执行的微操作如果有替换副本,我们将不会在端口上观察到活动。
由此得出的结论是,不替换使用掩码寄存器[15]的复制命令。

成瘾成语


使x86体系结构中的通用寄存器无效的最佳方法是使用异或逻辑(xor):xor regreg其作用基于以下事实:使用此操作将任何值与其自身进行比较都会得出零。该命令比更明显的mov eax短(占用更少的字节)0和更快,因为处理器知道这是一个重置习惯,并执行了必要的寄存器重命名[16],从而消除了对ALU和端口加载的需求。

而且,这种惯用法消除了数据依赖性:通常是命令xor reg1reg2的结果取决于reg1reg2寄存器中的值,但是在特殊情况下reg1和reg2包含相同的值时,就没有依赖性,因为对于任何输入值,输出将为零。所有现代x86处理器都认可这种[17]特例。这同样适用于异或成语的那些版本的事实,使用SIMD寄存器,即vpxor操作上整数和vxorpsvxorpd操作上实数。
在这里,好奇的读者可能会问:是否有类似这个成语的工作的的kxor命令?例如,将kxorb k1,k1,k1 [18] 命令视为重设习惯吗?
实际上,这是两个不同的问题,因为使用重置习语的效果由两个部分组成:

  • 零延迟执行绕过执行模块(执行消除
  • 消除依赖

我们将分别处理每个问题。

更换执行


因此,可以将具有xor的命令(例如kxorb k1,k1,k1)替换为重新分配的寄存器而不放置在执行模块中吗?

没有。

我什至无需自己做任何事情来证明这一点:所有信息都在uops.info网站上,因为他们进行了这样的测试,并表明该命令的执行延迟了1个时钟周期,并且对端口p0进行了一次微操作随之而来的是,掩码寄存器的“异或”重置惯用语不起作用。

消除依赖


但是,如果使用kxor的重置习惯用法仍然消除了数据依赖性,即使它们需要放置在执行模块中怎么办?

此处uops.info将无济于事。kxor命令具有1个时钟周期的延迟,并且在单个端口(p0)上执行,因此存在一种有趣的情况(?),其中kxor命令以相同的速度执行,而不管它们之间是否存在依赖关系:带宽能力1命令/周期的性能下降与延迟1命令/周期的下降相同!

没什么,我们还有一些技巧。以下测试将帮助我们回答这个问题。嵌入kxor在命令链中,每个后续命令都取决于前一个命令,并且该链的总执行时间应足够大以形成瓶颈。如果kxor命令没有消除依赖性,则链的总执行时间将等于其组成命令的延迟之和。如果依赖性消失,则链会分解成较短的序列,其延迟重叠,然后它们的执行速度将受到吞吐量的某个极限值的限制(例如,与端口竞争相关)。使用该方案可以清楚地表明这一点,但是我对此并不坚强。

所有这些测试可以在基准中找到uarch板凳但我将在下面给出重点。

首先,从通用寄存器测量标准复制时间,反之亦然:

kmovb k0, eax
kmovb eax, k0
;   127 

这些命令中的一对以4种方式执行[19]。尚不确切知道每个时间花了多少时间:2个小节或一个小节,另外3个小节[20]?但是,对于我们的任务来说这无关紧要,因为我们对来回复制的总时间感兴趣。值得注意的是,此序列的带宽为1个时钟周期,比延迟快4倍,因为每个命令都在其自己的端口(分别为p5p0)上执行。这意味着我们可以将延迟的影响与带宽的影响分开。

接下来,在我们的链中,包括kxor命令,可以确保不会导致大小写重置:

kmovb k0, eax
kxorb k0, k0, k1
kmovb eax, k0
;   127 

由于我们知道kxorb具有1个时钟周期的延迟,总的执行时间应增加至5个循环-这就是测试显示了(前两个测试的结果被示出):

**   avx512 :  AVX512 **
                                       
mov  GP  kreg                    4.00         1.25
mov  GP  kreg   + 
kxorb                              5.00         1.57

最后,主要测试:
kmovb k0, eax
kxorb k0, k0, k0
kmovb eax, k0
;   127 

这次我们使用带有大小写重置kxorb命令kxorb k0,k0,k0如果对寄存器k0中值的依赖性消失,则意味着kmovb eax,k0命令不再取决于先前的kmovb k0,eax命令,并且链已断开,总执行时间应减少。

鼓声...

我们得到了所有相同的5.0小节-与前面的示例相同:

**   avx512 :  AVX512 **
                                     
mov  GP  kreg                   4.00         1.25
mov  GP  kreg   + 
kxorb                             5.00         1.57
mov  GP  kreg   + 
kxorb                             5.00         1.57

初步结论是:如果将复位惯用语应用于屏蔽寄存器,则处理器不会识别它们。

总之,我们将进行另一次测试,以确保我们的推理是正确的:我们更换kxor用命令KMOV命令,正如你知道的,总是删除依赖关系:

kmovb k0, eax
kmovb k0, ecx
kmovb eax, k0
;   127 

最终答案如下。上一次测试要快得多-仅2个时钟周期,而瓶颈是端口p5kmov k,r32命令都仅在此端口上执行):

**   avx512 :  AVX512 **
                                       
mov  GP  kreg                   4.00            1.25
mov  GP  kreg   + 
kxorb                             5.00            1.57
mov  GP  kreg   + 
kxorb                             5.00            1.57
mov  GP  kreg   + 
mov  GP                                  2.00            0.63

事实证明,我们的假设是正确的。

播放结果


通过在Linux或Windows(在WSL下)运行robsize可执行文件您可以自己重现本文介绍的所有结果它们也可以在资源库中找到,以及用于收集和绘制它们的脚本

发现


  • SKX体系结构掩码寄存器位于单独的物理寄存器文件中。其中134个用于存储推测值,掩码寄存器的总数为142
  • 此数字可与其他类型的寄存器文件以及ROB缓冲区的大小相比,并且足够大,不会在使用掩码寄存器时出现性能下降
  • 带有掩码寄存器的复制命令不会被替换
  • [21]

  1. k- kregs – -. , k – «» (m) «» (f).
  2. ( AVX-512 ), k0 – , , , . : k0 – , , , k, SIMD-, (, AVX-512). SIMD- k0 , .
  3. , -, 0, , . , , , , - - .
  4. « », kreg – ( k0, k1 ..), – «kreg» « » ( ).
  5. H. Wong, Measuring Reorder Buffer Capacity, May, 2013. [Online]. (. , « », 2013. -.) : blog.stuffedcow.net/2013/05/measuring-rob-capacity
  6. 100 300 . , - 2 50 100 , – 2,5 (, 2 5 ). TLB-/ .
  7. «» . , , . . , 29 104, , – , 200. , ( ) – , - ( ), .
  8. , , , (register alias table, RAT), . RAT , , , , . RAT , , .
  9. 60% 134 224, .. PRF ROB. , ROB 224 , , , [10] 60% , ROB. , - , 60% , ROB, .
  10. , , . , (, SIMD- ), . [2]
  11. , . , 2 2 SIMD- ( ), 4 .
  12. Physical Register Reclaim Table ( ) Post Retirement Reclaim Table ( ).
  13. – , « », .. , , . , . : , .
  14. , ( 7) , PRF ROB.
  15. , , , . , ( , , , – ).
  16. RAT , RAT , , .
  17. xor, , sub reg,reg sbb reg, reg. , reg 0 -1 ( ) . , reg, – , . .
  18. , : kxorb k1, k1, k1 , kxorb k1, k2, k2.
  19. , ,

    ./uarch-bench.sh --test-name=avx512/*. 

  20. uops.info kmov r32, k, kmov k, 32 <= 3. , 4 . 1 , , 3 .
  21. , xor, , , -, , . , : , .

All Articles