我正在考虑简单的问题 - 加快计算两个双数组的分量乘积。我注意到使用AVX命令,与循环中的顺序乘法相比,我只获得了大约20%的加速。
我决定检查两种情况的延迟,并与加载操作的汇编代码混淆:
### __m256d pd;
### pd = _mm256_load_pd(a);
movq -112(%rbp), %rax //Pushing the pointer to the stack
vmovapd (%rax), %ymm0 //Pushing 32 bytes from memory to ymm
vmovapd %ymm0, -80(%rbp) //What is
vmovapd -80(%rbp), %ymm0 //happening here?
vmovapd %ymm0, -48(%rbp) //Quite slow down, since vmovapd cost ~ vmulpd
以上是以下C代码的汇编的一部分:
inline int test(double * a) {
__m256d pd;
pd = _mm256_load_pd(a);
return 1;
}
在__m256_load_pd的描述中,据说它是以这种方式完成的:
dst[255:0] := MEM[mem_addr+255:mem_addr]
dst[MAX:256] := 0
即。以相反的顺序?但是这两行汇编代码如何对此做任何事情?
答案 0 :(得分:0)
除了编译标志之外,如果没有更多的上下文,很难回答这个问题。根据操作的线程数和double数组的大小,可能是您的问题是内存限制,即性能受内存访问限制。
非常大的数据 您想查看Stream基准。使用AVX内在函数将有助于软件和硬件预取以及数据对齐,这可能解释了+ 20%。无论如何,你将受到内存限制(将数据从系统内存加载到L1缓存),并且与AVX操作相比,执行sequantialy操作将无关紧要,并且可能由并行发生的数据加载隐藏(由于预取的魔力)。 / p>
L2 CACHE中的数据 根据并发线程的数量,可以以更高的速度馈送数据。但是,对数据执行mul对数据的计算不够复杂,无法承担内存编组的成本。
L1 CACHE中的数据 对于这种情况,您可能会看到性能方面的一些改进,但可能还有其他一些因素,例如L1 Cache负载引起的执行依赖性和延迟。但是,在256位寄存器中加载对齐数据可能是性能最佳的。