assembly x86 AVX中是否有聚合操作?

bxgwgixi  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(124)

我正在尝试写一个简单的游戏,我需要学习一些x86汇编的向量操作。使用xmm作为4压缩单精度浮点数,是否有任何聚合操作?例如:
“MAXPS”计算4 fp32的最大值。(用于切比雪夫距离等)
“SUMPS”计算4 fp32的和。(用于点积或矢量幅度)

e4eetjau

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指令,并在末尾进行水平缩减)。
dpiehjr4

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);
}

相关问题