【问题标题】:How can i optimize this S-curve function?如何优化此 S 曲线功能?
【发布时间】:2016-01-18 11:52:16
【问题描述】:

我正在研究生成“S 曲线”的伽马函数。 我需要在实时环境中运行它,所以我需要尽可能加快它的速度。

代码如下:

float Gamma = 2.0f; //Input Variable

float GammaMult = pow(0.5f, 1.0f-Gamma);
if(Input<1.0f && Input>0.0f)
{
    if(Input<0.5f)
    {
        Output = pow(Input,Gamma)*GammaMult;
    }
    else
    {
        Output  = 1.0f-pow(1.0f-Input,Gamma)*GammaMult;
    }
}
else
{
   Output  = Input;
}

有什么办法可以优化这段代码吗?

【问题讨论】:

  • 浮点伽玛 = 2.0f; //输入变量当然应该是动态的吧?
  • 它是动态的,只是为了示例目的而设置。

标签: c++ gamma-function


【解决方案1】:

如果指令集支持saturation arithmetic 或使用最大/最小内在函数,您可以通过消除Input&lt;1.0f &amp;&amp; Input&gt;0.0f 上的分支来避免pipeline stalls,例如x86 MAXSS

您还应该通过将饱和的Input 舍入来消除其他分支。完整算法:

float GammaMult = pow(0.5f, 1.0f-Gamma);
Input = saturate(Input); // saturate via assembly or intrinsics
// Input is now in [0, 1]
Rounded = round(Input); // round via assembly or intrinsics
Coeff = 1 - 2 * Rounded
Output = Rounded + Coeff * pow(Rounded + Coeff * Input,Gamma)*GammaMult;

应该进行舍入via asm/intrinsics as well

如果您使用此功能,例如如果目标架构支持 SIMD,您应该考虑将数组的连续值向量化。

【讨论】:

  • 这里四舍五入有什么好处?原始代码似乎不希望将结果四舍五入为整数,并且只要您使用 FRNDINT 指令,您就不会通过避免浮点运算来支持整数运算来提高性能,因为这样就离开了浮点堆栈上的结果。
  • @CodyGray 舍入用于生成系数,因此他不需要在Input &lt; 0.5 上进行分支。例如:Coeff = 1 - 2 * Rounded 如果Input &lt; 0.5 则为 1,如果Input &gt; 0.5 则为-1,因此原始算法中的分支现在变成了一轮指令,一个浮点倍数和一个浮点数加 -> 流水线不会t受苦。
  • 哦,当然!非常聪明。我在粗略的阅读中错过了这一点。
  • SIMDed pow 在高端编译器之外并不是很普遍。
【解决方案2】:

您的代码看起来不错。瓶颈(如果存在)是pow 函数。唯一的解决方案是更深入地研究底层细节并尝试实现自己的pow 函数。例如,如果 2 个浮点数对您来说就足够了,您可能会发现一些基于近似的算法更快。

看到这个:The most efficient way of implementing pow() function in floating point

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多