我正在尝试写一个简单的游戏,我需要学习一些x86汇编的向量操作。使用xmm作为4压缩单精度浮点数,是否有任何聚合操作?例如:“MAXPS”计算4 fp32的最大值。(用于切比雪夫距离等)“SUMPS”计算4 fp32的和。(用于点积或矢量幅度)
e4eetjau1#
TLDR:有一些减少指令,但通常你应该遵循:Fastest way to do horizontal SSE vector sum (or other reduction)唯一的浮点指令(我知道的),做水平减少是
haddps
haddpd
dpps
dppd
fma
dpiehjr42#
一种非循环、非分支的方法来获取SSE向量的最大浮点值,如下所示。
inline float _mm_hmax_ps(__m128 arg) { // Returns the maximum 32 bit float value in arg. // Requires SSE. __m128 temp, temp2; temp = _mm_shuffle_ps(arg, arg, 78); // 78 = 01001110b temp = _mm_max_ps(arg, temp); temp2 = _mm_shuffle_ps(temp, temp, 165); // 165 = 10100101b temp2 = _mm_max_ps(temp2, temp); return _mm_cvtss_f32(temp2); }
字符串AVX版本如下。
inline float _mm256_hmax_ps(__m256 arg) { // Returns the maximum 32 bit float value in arg. // Requires AVX1 & SSE1. __m128 temp128u, temp128l; __m256 temp, temp2; temp = _mm256_shuffle_ps(arg, arg, 78); // 78 = 01001110b temp = _mm256_max_ps(arg, temp); temp2 = _mm256_shuffle_ps(temp, temp, 165); // 165 = 10100101b temp = _mm256_max_ps(temp2, temp); temp128u = _mm256_extractf128_ps(temp, 1); temp128l = _mm256_extractf128_ps(temp, 0); temp128u = _mm_max_ps(temp128u, temp128l); return _mm_cvtss_f32(temp128u); }
型
2条答案
按热度按时间e4eetjau1#
TLDR:有一些减少指令,但通常你应该遵循:Fastest way to do horizontal SSE vector sum (or other reduction)
唯一的浮点指令(我知道的),做水平减少是
haddps
/haddpd
:这些将来自两个输入寄存器的两个相邻值相加,并将它们堆叠到一个输出寄存器中(通常的怪癖是,AVX 256就像两个独立的SSE/AVX 128操作)。如果您想将单个寄存器减少为标量,请不要使用这些寄存器(参见上面的链接答案)。dpps
/dppd
:计算(最多)4个元素的点积(dpps
)或最多两个元素(dppd
)。这通常只在你的主要目标是小的二进制大小时才值得使用,或者在屏蔽输入/输出的特殊情况下。dppd
指令显然根本没有移植到256位。此外,永远不要将其用作大型点积的构建块(这些应该在主循环中仅使用fma
指令,并在末尾进行水平缩减)。dpiehjr42#
一种非循环、非分支的方法来获取SSE向量的最大浮点值,如下所示。
字符串
AVX版本如下。
型