【问题标题】:C Intrinsics Efficiency - Which is better?C 内在效率 - 哪个更好?
【发布时间】:2016-06-11 16:43:31
【问题描述】:

我目前正在优化一个程序,我需要计算多个类型__m128 的倒数平方根。最初,在矢量化之前(当数字是浮点数时),它只是ans = 1.0f / sqrt(num),但现在我有_mm_rsqrt_ps(num)。唯一的问题是,在处理更大的数据集时,这会在一定程度上影响我的答案。

我想知道_mm_div_ps()_mm_sqrt_ps 函数的使用是否会更准确(尽管我预计需要更多时间),以及如何将1.0f 分配给键入__m128

谢谢。

【问题讨论】:

  • __m128 是单精度浮点类型的 4 元素向量,不能为其分配单个浮点数。
  • 有时 sqrt 是通过将输入乘以 rsqrt 来计算的,因为这样更容易,我怀疑做 1/sqrt 有助于提高精度
  • 那么,例如,我如何获得一些 __m128 来包含 1.0 的值,以便我可以使用 _mm_div_ps(1_v, sqrt_v)
  • 您怀疑它有助于提高精度?
  • 或者你可以试试这个stackoverflow.com/questions/14752399/…

标签: c performance intrinsics


【解决方案1】:

我想知道使用 _mm_div_ps() 和 _mm_sqrt_ps 函数是否会更准确

当然,因为rsqrtps 不是一个精确的运算,所以它的全部意义在于它是一个近似值。正如您可以在 intrinsic guide 的手册中阅读的那样,

这个近似值的相对误差是:

|相对误差| ≤ 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 仍然会降低吞吐量。

上面的代码还展示了如何获取向量中的常量。

【讨论】:

    猜你喜欢
    • 2020-06-18
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多