cxx*_*xxl 15 assembly sse bignum avx arbitrary-precision
当我正在进行快速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
Run Code Online (Sandbox Code Playgroud)
然后我将其升级到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
Run Code Online (Sandbox Code Playgroud)
后来我使用了AVX(每个寄存器256位).我有2个这样的块:
vmovdqa ymm0, YMMWORD PTR [rdx+r11*8-64]
vmovdqa ymm1, YMMWORD PTR [r8+r11*8-64]
vmovdqa YMMWORD PTR [rcx+r11*8-64], ymm0
Run Code Online (Sandbox Code Playgroud)
到目前为止,还不那么引人注目.有趣的是基准测试的结果:当我在1K + 1K = 1K 64位字(即两次输入的8 kb和一次输出的8KB)运行三种不同的方法,我得到了奇怪的结果.以下每个时序用于处理两次64字节输入到64字节输出.
我的问题是:为什么AVX方法比SSE2方法慢(虽然不是很多)?我预计它至少会与之相提并论.使用YMM寄存器会花费多少额外的时间吗?内存已对齐(否则会获得GPF).
有没有人对此有解释?
Ste*_*non 12
在Sandybridge/Ivybridge上,256b AVX加载和存储被破解为两个128b操作[正如Peter Cordes所说,这些不是很好,但在加载/存储执行单元中需要两个周期来清除端口],因此没有理由期望使用这些指令的版本更快.
它为什么慢?我想到了两种可能性:
对于基数+索引+偏移量寻址,128b负载的延迟为6个周期,而256b负载的延迟为7个周期(英特尔优化手册中的表2-8).尽管您的基准测试应该受到吞吐量而非延迟的限制,但延迟时间越长意味着处理器需要更长时间才能从任何打嗝(管道气泡或预测未命中或服务中断或......)中恢复,这确实会产生一些影响.
在同一文件的11.6.2中,英特尔建议高速缓存行和页面交叉的惩罚可能比256b负载的256b负载更大.如果您的加载不是全部32字节对齐,这也可以解释您在使用256b加载/存储操作时看到的速度减慢:
例11-12显示了具有未对齐地址的SAXPY的两种实现.备选1使用32字节加载,备选2使用16字节加载.这些代码样品用两个源缓冲剂,SRC1,SRC2执行时,在4字节的从32字节对齐偏移,以及目标缓冲区,DST,即对齐的32字节.使用两个16字节内存操作代替32字节内存访问执行速度更快.