1

出于准确性原因,我经常需要使用双精度,但我想将结果存储为浮点数。什么是最佳方式?我目前正在使用:

上交所2:_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));

有什么改进的想法吗?

4

1 回答 1

2

从 packed-double 到 packed-float 的转换只能以缩小形式提供,而不是在采用 2 个 double 向量并打包成 1 个 float 向量的版本中。所以是的,内在函数[v]cvtpd2ps是你唯一的选择。这些指令在现代英特尔上解码为 2 微指令;一个用于 FMA 端口,一个用于 shuffle 端口。(https://agner.org/optimize/

存储结果很简单,某种形式的_mm_store/storeu就是你想要的。


对于 128 位向量(导致 2x float= 64 位),您没有完整的 128 位向量结果。您可以将两个混洗到一个 128 位向量中,但是自从 Sandybridge 以来,英特尔上的 FP 混洗吞吐量为每个时钟 1 个,最好将它们分开存储。

您不想存储movlps向量movsd的低 64 位float;它节省了一个指令字节,并且 C 内在函数使用更少的转换。但不幸的是,它需要 a__m64*而不是 a float*,所以你仍然需要一个演员表:

_mm_storel_pi((__m64*)dst,   _mm_cvtpd_ps(xmm) );

但是对于加载,您肯定希望movsd避免对旧值的错误依赖。 movlps加载合并到一个寄存器中;movsd加载零扩展。实际上,cvtps2pd xmm, qword [mem]如果您可以让编译器从内在函数中发出它,那么会为您解决这个问题。

由于类似的原因,可能很难安全地做到这一点pmovzxbw xmm, qword [mem]:编译器无法将 qword 加载折叠到 pmovzx/sx 的内存操作数中:(将8 个字符从内存加载到 __m256 变量中作为打包单精度浮点数

于 2018-10-18T16:42:59.900 回答