【问题标题】:Vmovntpd instruction on Intel Xeon Platinum 8168 CPUIntel Xeon Platinum 8168 CPU 上的 Vmovntpd 指令
【发布时间】:2019-11-22 11:13:53
【问题描述】:

我在汇编中有一个简单的向量-向量加法算法实现。它使用 AVX 从 A 向量中读取 4 个双精度值,从 B 向量中读取 4 个双精度值。该算法将这些数字相加并将结果写回 C 向量。如果我使用 vmovntpd 写回结果,性能变得非常随机。我在配备 Intel Xeon Platinum 8168 CPU 的天蓝色服务器上进行了此测试。如果我在笔记本电脑(Intel Core i7-2640M CPU)上运行这个测试,这个随机效应就会消失。服务器有什么问题?另一个信息:服务器有 44 个 CPU-s。

[编辑] 这是我的代码:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dense to dense
;; Without cache (for storing the result)
;; AVX-512
;; Without tolerances
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

global _denseToDenseAddAVX512_nocache_64_linux
_denseToDenseAddAVX512_nocache_64_linux:

push    rbp
mov     rbp, rsp
; c = a + lambda * b
; rdi: address1
; rsi: address2
; rdx: address3
; rcx: count
; xmm0: lambda

mov     rax, rcx
shr     rcx, 4
and     rax, 0x0F

vzeroupper

vmovupd  zmm5, [abs_mask]

sub     rsp, 8
movlpd  [rbp - 8], xmm0
vbroadcastsd    zmm7, [rbp - 8]
vmovapd  zmm6, zmm7

cmp     rcx, 0
je      after_loop_denseToDenseAddAVX512_nocache_64_linux

start_denseToDenseAddAVX512_nocache_64_linux:

vmovapd  zmm0, [rdi] ; a
vmovapd  zmm1, zmm7
vmulpd   zmm1, zmm1, [rsi] ; b
vaddpd   zmm0, zmm0, zmm1  ; zmm0 = c = a + b
vmovntpd  [rdx], zmm0

vmovapd  zmm2, [rdi + 64] ; a
vmovapd  zmm3, zmm6
vmulpd   zmm3, zmm3, [rsi + 64] ; b
vaddpd   zmm2, zmm2, zmm3  ; zmm2 = c = a + b
vmovntpd  [rdx + 64], zmm2

add     rdi, 128
add     rsi, 128
add     rdx, 128

loop    start_denseToDenseAddAVX512_nocache_64_linux

after_loop_denseToDenseAddAVX512_nocache_64_linux:

cmp     rax, 0
je      end_denseToDenseAddAVX512_nocache_64_linux

mov     rcx, rax

last_loop_denseToDenseAddAVX512_nocache_64_linux:

movlpd  xmm0, [rdi] ; a
movapd  xmm1, xmm7
mulsd   xmm1, [rsi] ; b
addsd   xmm0, xmm1  ; xmm0 = c = a + b
movlpd  [rdx], xmm0

add     rdi, 8
add     rsi, 8
add     rdx, 8

loop    last_loop_denseToDenseAddAVX512_nocache_64_linux

end_denseToDenseAddAVX512_nocache_64_linux:

mov     rsp, rbp
pop     rbp
ret

【问题讨论】:

  • 您是否将商店分组到完整的缓存行中?还是您任意混合负载和 NT 存储?可能很容易成为问题,尤其是如果您的虚拟服务器在与另一个非空闲线程相同的物理内核上运行您的代码时。再说了,我们需要你的代码的minimal reproducible example 以及你如何编译它(编译器/版本/选项),或者至少是内部循环的 asm。
  • 您应该在问题本身中发布您的代码!您是否有意在主循环之后使用旧版 SSE 指令? (movlpd xmm0, [rdi] 会引入错误的依赖关系。)您是否有意避免 FMA 指令?为什么要复制这么多而不是利用 3 个寄存器操作数?从不使用开头的vmovupd zmm5, [abs_mask]
  • @Pocokman Stack Overflow 问题必须是独立的。编辑您的问题以添加您的代码。我不会查看外部网站来收集您的问题。
  • 考虑使用内在函数在 C/C++ 中重写您的代码。编译器不会犯像使用 LOOP 指令这样的基本错误。
  • 一个问题是在使用SSE指令之前没有vzerouppervzeroupper 指令应放置在 AVX 指令的每个部分的末尾,以避免部分寄存器处罚。或者,将这些指令翻译成 AVX 指令,然后发出vzeroupper

标签: performance assembly intel avx cpu-cache


【解决方案1】:

好的,我找到了解决方案!这是一个有 44 个 CPU 的 NUMA 架构,所以我禁用了 NUMA,并使用以下内核参数将在线 cpu-s 的数量限制为 1:numa=off maxcpus=1 nr_cpus=1。

【讨论】:

  • 这是 a 解决方案,但几乎没有用处。如果您只想使用单核,您还不如购买桌面 Skylake-X 而不是 44 核 Xeon。这更像是缩小问题范围的一步,例如NUMA 可能是问题所在。当所有 CPU 都处于活动状态时,使用 taskset 将您的程序固定到单核是否有帮助?
  • 使用 azure 服务器(最多 10 小时)比购买新 CPU 或计算机便宜,但我会记住这个 Skylake-X,谢谢 :)
  • 如果你不选择多线程,你肯定可以为单CPU VM实例支付更少的费用吗?
猜你喜欢
  • 2021-08-31
  • 2013-09-29
  • 2015-10-16
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 2014-05-05
  • 2020-04-23
  • 1970-01-01
相关资源
最近更新 更多