首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么SSE标量sqrt(X)比rsqrt(X)*x慢?

为什么SSE标量sqrt(X)比rsqrt(X)*x慢?
EN

Stack Overflow用户
提问于 2018-04-13 06:10:46
回答 2查看 0关注 0票数 0

我在Intel Core Duo上分析了我们的一些核心数学,在查看各种平方根的方法时,我注意到了一些奇怪的东西:使用SSE标量运算,取一个倒数平方根并乘以它得到sqrt比使用本机sqrt操作系统更快!

我正在用一个循环来测试它,类似于:

inline float TestSqrtFunction( float in );

void TestFunc()
{
  #define ARRAYSIZE 4096
  #define NUMITERS 16386
  float flIn[ ARRAYSIZE ]; // filled with random numbers ( 0 .. 2^22 )
  float flOut [ ARRAYSIZE ]; // filled with 0 to force fetch into L1 cache

  cyclecounter.Start();
  for ( int i = 0 ; i < NUMITERS ; ++i )
    for ( int j = 0 ; j < ARRAYSIZE ; ++j )
    {
       flOut[j] = TestSqrtFunction( flIn[j] );
       // unrolling this loop makes no difference -- I tested it.
    }
  cyclecounter.Stop();
  printf( "%d loops over %d floats took %.3f milliseconds",
          NUMITERS, ARRAYSIZE, cyclecounter.Milliseconds() );
}

我在TestSqrtFunction中尝试了几个不同的工具,而且我也有一些非常费劲的时间。最糟糕的是使用本机sqrt()函数并让“智能”编译器“优化”。在24 ns/Float,使用X87 FPU,这是可悲的坏:

inline float TestSqrtFunction( float in )
{  return sqrt(in); }

接下来我尝试的是使用内部代码强制编译器使用SSE的标量sqrt操作码:

inline void SSESqrt( float * restrict pOut, float * restrict pIn )
{
   _mm_store_ss( pOut, _mm_sqrt_ss( _mm_load_ss( pIn ) ) );
   // compiles to movss, sqrtss, movss
}

最糟糕的是当我尝试SSE的时候互惠性,然后使用乘法得到平方根(X)。*1/√x=√x)。尽管这需要两个依赖操作,但它是迄今为止最快的解决方案,以1.24ns/Float计算,精确到2-14:

inline void SSESqrt_Recip_Times_X( float * restrict pOut, float * restrict pIn )
{
   __m128 in = _mm_load_ss( pIn );
   _mm_store_ss( pOut, _mm_mul_ss( in, _mm_rsqrt_ss( in ) ) );
   // compiles to movss, movaps, rsqrtss, mulss, movss
}

我的问题基本上是是什么为什么SSE的内建硬件平方根操作码? 慢点 而不是从其他两个数学运算中合成它?

我确信这就是OP本身的成本,因为我已经验证了:

  • 所有数据都符合高速缓存,并且访问是连续的。
  • 这些函数是内联的。
  • 展开循环没有什么区别。
  • 编译器标志被设置为完全优化(我检查过的程序集很好)
EN

回答 2

Stack Overflow用户

发布于 2018-04-13 14:11:21

sqrtss给出一个正确的四舍五入的结果。rsqrtss给出一个近似到倒数,精确到大约11位。

sqrtss正在产生一个更精确的结果,当需要精确的时候。rsqrtss如果你读了英特尔的文档,你也会发现指令序列(倒数平方根近似,然后是一个牛顿-拉夫森步),它提供了几乎完全的精度(如果我记得的话,大约有23位的精度),并且仍然比它的速度要快一些。sqrtss

编辑:如果速度是关键的,并且你真的在循环中对许多值调用它,你应该使用这些指令的矢量化版本,rsqrtpssqrtps,每条指令处理四个浮点。

票数 0
EN

Stack Overflow用户

发布于 2018-04-13 16:07:54

除法也是如此。MULSS(a,RCPSS(B))比DIVSS(a,b)要快得多。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100008099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档