AVX-512多核而不是单核的缓存命中率

如何解决AVX-512多核而不是单核的缓存命中率

以下是NASM程序的循环主体(循环主体表示我没有显示实例化内核和共享内存,读取输入数据,将最终结果写入文件的部分)。该程序是从C包装程序中调用的共享对象。显示了其中9条线的行号;它们与下面的注释中引用的行号相对应。

mov rax,255
kmovq k7,rax

label_401:

    cmp r11,r10
    jge label_899

    vmovupd zmm14,[r12+r11] ;[185]
    add r11,r9 ; stride ;[186]

    vmulpd zmm13,zmm14,zmm31 ; [196]

    vmulpd zmm9,zmm29 ; [207]
    vmulpd zmm8,zmm13,zmm30

    mov r8,1
    Exponent_Label_0:
    vmulpd zmm7,zmm29,zmm29
    add r8,1
    cmp r8,2 ;rdx
    jl Exponent_Label_0

    vmulpd zmm3,zmm7,zmm8

    vsubpd zmm0,zmm9,zmm3

    vmulpd zmm1,zmm0,zmm28
    VCVTTPD2QQ zmm0{k7},zmm1 ; [240]
    VCVTUQQ2PD zmm2{k7},zmm0 ; [241]
    vsubpd zmm3,zmm1,zmm2
    vmulpd zmm4,zmm3,zmm27 ; [243]
    VCVTTPD2QQ zmm5{k7}{z},zmm4

    VPCMPGTQ k2,zmm5,zmm26
    VPCMPEQQ k3 {k7},zmm26
    KADDQ k1,k2,k3

    VCVTQQ2PD zmm2{k7},zmm0 ; [252]
    vmulpd zmm1{k7},zmm2,zmm25
    vmovupd zmm2,zmm1
    VADDPD zmm2{k1},zmm25

    vmovapd [r15+r14],zmm2 ; [266]
    add r14,r9 ; stride
    jmp label_401

该程序仅在第185行读取的数据之间使用AVX-512寄存器到寄存器指令,然后将最终结果写入第266行的共享内存缓冲区。我在1个核和4个核上运行了该指令,但4核版本比单核慢2-3倍。我使用Linux性能分析了它,以了解为什么多核AVX-512的速度比单核要慢2-3倍。

下面显示的perf报告是通过运行所有65个具有perf record / perf批注的PEBS计数器完成的-通过源代码行查看结果-通过perf stat获取全部计数。每个perf记录和perf stat计数器都是单独运行的,结果按源代码行进行汇总,来自perf stat的计数分别显示在下面。

每条指令后都有源代码行号。对于性能记录指令,它在源代码行中显示该计数器的百分比,并在每行末尾的括号中显示此类指令的总数(来自性能统计)。

我的主要问题是,为什么我们在AVX-512指令中看到的多核缓存命中率和未命中率都是寄存器到寄存器指令,而在单核上却没有相同的指令。对于完全在寄存器内的指令,不应有任何高速缓存命中或丢失。每个内核都有自己的一组寄存器,因此在指令全部为寄存器对寄存器的情况下,我不希望发生任何缓存活动。当仅使用单个内核运行时,我们几乎看不到所有寄存器指令中的缓存活动。

1.  Line 186 - add r11,r9
mem_inst_retired.all_loads     75.00% (447119383)
mem_inst_retired.all_stores    86.36% (269650353)
mem_inst_retired.split_loads   71.43% (6588771)
mem_load_retired.l1_hit        57.14% (443561879)

Single core (line 177) - add r11,r9
mem_inst_retired.all_stores    24.00% (267231461)

该指令(加r11,r9)加两个寄存器。当使用单核时,我们看不到任何缓存命中/未命中或内存负载,但是使用多核时,我们可以看到。为什么这里有多核而不是单核的缓存命中和内存加载指令?

2.  Line 196 - vmulpd zmm13,zmm31
mem_inst_retired.split_loads     28.57% (6588771)
mem_load_retired.fb_hit         100.00% (8327967)
mem_load_retired.l1_hit         14.29% (443561879)
mem_load_retired.l1_miss        66.67% (11033416)

Single core (line 187) - vmulpd zmm13,zmm31
mem_load_retired.fb_hit 187 100.00% (8889146)

该指令(vmulpd zmm13,zmm14,zmm31)是所有寄存器,但再次显示了L1命中,未命中以及使用多核而不是单核的负载分割。

3. Line 207 - vmulpd zmm9,zmm29
mem_load_retired.l1_hit           14.29% (443561879)
mem_load_retired.l1_miss          33.33% (11033416)
rs_events.empty_end               25.00% (37013411)

Single core (line 198):
mem_inst_retired.all_stores       24.00% (267231461)
mem_inst_retired.stlb_miss_stores 22.22%

此指令(vmulpd zmm9,zmm14,zmm29)与上述指令(vmulpd,所有寄存器)相同,但再次显示了L1命中,未命中以及使用多核而不是单核拆分负载。单核确实显示了第二级TLB丢失,并且存储了已退休的指令,但是没有缓存活动。

4.  Line 240 - VCVTTPD2QQ zmm0{k7},zmm1
mem_inst_retired.all_loads               23.61% (447119383)
mem_inst_retired.split_loads             26.67% (6588771)
mem_load_l3_hit_retired.xsnp_hitm        28.07% (1089506)
mem_load_l3_hit_retired.xsnp_none        12.90% (1008914)
mem_load_l3_miss_retired.local_dram      40.00% (459610)
mem_load_retired.fb_hit                  29.21% (8327967)
mem_load_retired.l1_miss                 19.82% (11033416)
mem_load_retired.l2_hit                  10.22% (12323435)
mem_load_retired.l2_miss                 24.84% (2606069)
mem_load_retired.l3_hit                  19.70% (700800)
mem_load_retired.l3_miss                 21.05% (553670)

Single core line 231:
mem_load_retired.l1_hit                  25.00% (429499496)
mem_load_retired.l3_hit                  50.00% (306278)

此行(VCVTTPD2QQ zmm0 {k7},zmm1)是寄存器到寄存器。单核显示L1和L3活动,而多核显示更多的缓存活动。

5.  Line 241 - VCVTUQQ2PD zmm2{k7},zmm0
mem_load_l3_hit_retired.xsnp_hitm        21.05% (1089506)
mem_load_l3_miss_retired.local_dram      10.00% (459610)
mem_load_retired.fb_hit                  10.89% (8327967)
mem_load_retired.l2_miss                 13.07% (2606069)
mem_load_retired.l3_miss                 10.53%

Single core line 232:
Single core has no cache hits or misses reported
mem_load_retired.l1_hit                  12.50% (429499496)

全寄存器指令(VCVTUQQ2PD zmm2 {k7},zmm0)显示了多核具有很多缓存活动,但单核只有少量L1命中(12.5%)。我不希望看到带有全寄存器指令的缓存命中/未命中或加载/存储指令。

6.  Line 243 - vmulpd zmm4,zmm27
br_inst_retired.all_branches_pebs        12.13% (311104072)

Single core line 234:
mem_load_l3_hit_retired.xsnp_none        100.00% (283620)

为什么我们看到全寄存器mul指令的分支指令?

7.  Line 252 - VCVTQQ2PD zmm2{k7},zmm0
br_inst_retired.all_branches_pebs     16.62% (311104072)
mem_inst_retired.all_stores           21.22% (269650353)

Single core line 243:
Single core also has branch instructions
br_inst_retired.all_branches_pebs     22.16% (290445009)

对于寄存器对寄存器指令(VCVTQQ2PD zmm2 {k7},zmm0),为什么我们看到分支指令?该指令不会分支,也不会在分支之前或之后。

8.  Line 266 - vmovapd [r15+r14],zmm2
br_inst_retired.all_branches_pebs 43.56% (311104072)
mem_inst_retired.all_loads        48.67% (447119383)
mem_inst_retired.all_stores       43.09% (269650353)
mem_inst_retired.split_loads      41.30% (6588771)
mem_inst_retired.stlb_miss_loads  11.36% (487591)
mem_inst_retired.stlb_miss_stores 12.50% (440729)
mem_load_l3_hit_retired.xsnp_hitm 33.33% (1089506)
mem_load_l3_hit_retired.xsnp_none 56.45% (1008914)
mem_load_l3_miss_retired.local_dram 35.00% (459610)
mem_load_retired.fb_hit             39.60% (8327967)
mem_load_retired.l1_hit             48.75% (443561879)
mem_load_retired.l1_miss            51.65% (11033416)
mem_load_retired.l2_hit             71.51% (12323435)
mem_load_retired.l2_miss            45.10% (2606069)
mem_load_retired.l3_hit             59.09% (700800)
mem_load_retired.l3_miss            47.37% (553670)

Single core line 257:
mem_inst_retired.all_loads          84.86% (426023012)
mem_inst_retired.all_loads 
mem_inst_retired.all_stores         59.28% (267231461)
mem_inst_retired.split_loads        89.92% (6477955)
mem_load_l3_miss_retired.local_dram 100.00% (372586)
mem_load_retired.fb_hit              92.80% (8889146)
mem_load_retired.l1_hit              54.17% (429499496)
mem_load_retired.l1_miss             91.30% (4170386)
mem_load_retired.l2_hit             100.00% (4564407)
mem_load_retired.l2_miss            100.00% (476024)
mem_load_retired.l3_hit              33.33% (306278)

此行(vmovapd [r15 + r14],zmm2)可能是最有可能影响单核与多核之间差异的线。在这里,我们将最终结果传输到所有内核共享的内存缓冲区。由于内存移动,我们希望看到多核和单核的缓存活动。单核使用通过malloc创建的单个缓冲区。对于多核,它是posix共享内存,因为它的运行速度比使用malloc创建的数组要快得多。

单核和多核都在2.30GHz的Intel Xeon Gold 6140 CPU上运行,该处理器具有两个用于AVX-512的FMA单元。

总而言之,我的问题是:(1)为什么我们在使用AVX-512多核而不是单核的寄存器对寄存器指令中看到缓存活动(少数情况除外); (2)有什么方法可以完全绕过vmovapd [r15 + r14],zmm2处的高速缓存并直接进入内存以避免高速缓存未命中吗? Posix共享内存是一项改进,但是并不能完全做到这一点。最后,还有其他原因导致多核AVX-512的速度比单核慢吗?

更新:此代码的访问模式由AVX决定-步幅为(64 x内核数)字节。对于4个内核,内核0从0开始,读取和处理64个字节,然后跳转256(64x4);核心1从64开始,读取和处理64个字节,然后跳转256,依此类推。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com(将#修改为@)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?