在我处理快速 ADD 循环(加速 x64 汇编器 ADD 循环)时,我正在使用 SSE 和 AVX 指令测试内存访问。要添加,我必须读取两个输入并产生一个输出。所以我写了一个虚拟例程,它将两个 x64 值读入寄存器并将一个写回内存而不做任何操作。这当然没用,我只是为了进行基准测试。
我使用一个展开的循环,每个循环处理 64 个字节。它由 8 个块组成,如下所示:
mov rax, QWORD PTR [rdx+r11*8-64]
mov r10, QWORD PTR [r8+r11*8-64]
mov QWORD PTR [rcx+r11*8-64], rax
然后我将其升级到 SSE2。现在我使用 4 个这样的块:
movdqa xmm0, XMMWORD PTR [rdx+r11*8-64]
movdqa xmm1, XMMWORD PTR [r8+r11*8-64]
movdqa XMMWORD PTR [rcx+r11*8-64], xmm0
后来我使用了 AVX(每个寄存器 256 位)。我有两个这样的块:
vmovdqa ymm0, YMMWORD PTR [rdx+r11*8-64]
vmovdqa ymm1, YMMWORD PTR [r8+r11*8-64]
vmovdqa YMMWORD PTR [rcx+r11*8-64], ymm0
到目前为止,还没有那么壮观。有趣的是基准测试结果:当我对 1k+1k=1k 64 位字(即两次 8 kb 输入和一次 8kb 输出)运行三种不同的方法时,我得到了奇怪的结果。以下每个时序用于将两次 64 字节输入处理为 64 字节输出。
- x64 寄存器方法以大约 15 个周期/64 字节运行
- SSE2 方法以大约 8.5 个周期/64 字节运行
- AVX 方法以大约 9 个周期/64 字节运行
我的问题是:为什么 AVX 方法比 SSE2 方法慢(虽然不是很多)?我预计它至少会达到同等水平。使用 YMM 寄存器会花费这么多额外的时间吗?内存是对齐的(否则你会得到 GPF)。
有人对此有解释吗?