我目前正在优化一个程序,我需要计算多个类型__m128
的倒数平方根。最初,在矢量化之前(当数字是浮点数时),它只是ans = 1.0f / sqrt(num)
,但现在我有_mm_rsqrt_ps(num)
。唯一的问题是,当处理更大的数据集时,这会使我的答案有所帮助。
我想知道_mm_div_ps()
和_mm_sqrt_ps
函数的使用是否更准确(虽然我希望花更多时间),并且在旁注中,如何指定1.0f
输入__m128
。
感谢。
答案 0 :(得分:3)
我想知道是否使用_mm_div_ps()和_mm_sqrt_ps函数会更准确
当然,因为rsqrtps
不是一个精确的操作,所以它的全部意义在于它是一个近似值。正如您可以阅读内在指南中的手册,
此近似值的相对误差为:
|相对错误| ≤1.5* 2 -12
你可能会想要将其视为“大概有意义的位的前半部分是正确的”,但它比这更令人讨厌,它喜欢在看起来微不足道的情况下给出不精确的结果。例如,如果你输入4,你可能会得到0.499878(现在我的电脑上的实际结果)。
这并不一定意味着你需要一个完整的平方根和除法。也许你这样做,但通常将rsqrtps
与精炼步骤(未经测试)结合使用就足够了:
__m128 y = _mm_rsqrt_ps(num);
__m128 yy = _mm_mul_ps(y, y);
__m128 hnum = _mm_mul_ps(num, _mm_set1_ps(0.5f));
__m128 threehalves = _mm_set1_ps(1.5f);
__m128 res = _mm_mul_ps(y, _mm_sub_ps(threehalves, _mm_mul_ps(yy, hnum)));
这精确到大约两倍于之前的位数。上面的技巧不一定是一个很大的胜利(取决于代码的使用方式),在Core2 45nm上,分区特别是平方根速度非常慢,但是从IB和更新的它几乎与延迟相关。即使在Skylake上,使用sqrt和div仍然会损失吞吐量。
上面的代码还展示了如何在向量中获取常量。