出于准确性的原因,我经常需要使用double,但是我想将结果存储为浮点数。最佳方法是什么?我目前正在使用:
SSE2:_mm_store_sd((double*)dst, _mm_castps_pd(_mm_cvtpd_ps(xmm)));
AVX:_mm_storeu_ps(dst, _mm256_cvtpd_ps(ymm));
AVX512:_mm256_storeu_ps(dst, _mm512_cvtpd_ps(zmm));
有什么改进想法吗?
答案 0 :(得分:2)
只能从缩小的格式转换为从packed-double转换为packet-float,不适用于需要将2个double向量打包为1个float向量的版本。因此,是的,[v]cvtpd2ps
的内在函数是您唯一的选择。这些指令在现代Intel上解码为2微秒;一个用于FMA端口,另一个用于随机播放端口。 (https://agner.org/optimize/)
存储结果非常简单,您想要的是_mm_store/storeu
的某种形式。
对于128位向量(结果为2x float
= 64位),您没有完整的128位向量结果。您可以将两个数据一起改组为一个128位向量,但是自Sandybridge以来,英特尔的FP数据交换吞吐量为每个时钟1个,最好将它们分别存储。
您希望movlps
而不是movsd
存储float
向量的低64位;它节省了一个指令字节,并且C内在函数使用较少的强制转换。但不幸的是,它需要使用__m64*
而不是float*
,因此您仍然需要进行一次强制转换:
_mm_storel_pi((__m64*)dst, _mm_cvtpd_ps(xmm) );
但是对于加载,您确实希望movsd
避免对旧值的错误依赖。 movlps
个负载合并到一个寄存器中; movsd
加载零扩展。实际上,如果您可以让编译器从内部函数发出该信息,cvtps2pd xmm, qword [mem]
会为您解决这个问题。
由于与pmovzxbw xmm, qword [mem]
类似的原因,可能很难安全地执行此操作:编译器无法将qword加载折叠到pmovzx / sx的内存操作数中:(Loading 8 chars from memory into an __m256 variable as packed single precision floats)