std :: fabs()的优化不好?

Sha*_*ggi 12 c++ bit-manipulation

最近我正在使用一个类似于以下代码的应用程序:

for (auto x = 0; x < width - 1 - left; ++x)
{
    // store / reset points
    temp = hPoint = 0;
    for(int channel = 0; channel < audioData.size(); channel++)
    {
        if (peakmode) /* fir rms of window size */
        {
            for (int z = 0; z < sizeFactor; z++)
            {
                temp += audioData[channel][x * sizeFactor + z + offset];
            }
            hPoint += temp / sizeFactor;
        }
        else /* highest sample in window */
        {
            for (int z = 0; z < sizeFactor; z++)
            {
                temp = audioData[channel][x * sizeFactor + z + offset];
                if (std::fabs(temp) > std::fabs(hPoint))
                hPoint = temp;
            }
        }
        .. some other code
    }
    ... some more code
}
Run Code Online (Sandbox Code Playgroud)

这是一个图形渲染循环,称为50-100次/秒,多个通道中的缓冲区高达192kHz.因此,通过最内层循环运行的是大量数据,并且分析显示这是一个热点.

在我看来,可以将浮点数转换为整数并擦除符号位,然后仅使用临时值将其转换回来.它看起来像这样:

if ((const float &&)(*((int *)&temp) & ~0x80000000) > (const float &&)(*((int *)&hPoint) & ~0x80000000))
    hPoint = temp;
Run Code Online (Sandbox Code Playgroud)

这使渲染时间减少了12倍,同时仍然产生相同的有效输出.请注意,audiodata中的所有内容都要事先清理,以便不包含nans/infs/denormals,并且只有[-1,1]的范围.

是否存在此优化会产生错误结果的极端情况 - 或者,为什么标准库函数没有像这样实现?我认为它与处理非正常值有关?

e:浮点模型的布局符合ieee,sizeof(float)== sizeof(int)== 4

MSa*_*ers 4

好吧,您将浮点模式设置为符合 IEEE 标准。通常,使用类似的开关--fast-math编译器之类的开关可以忽略 IEEE 极端情况,例如 NaN、INF 和非正规值。如果编译器也使用内在函数,它可能会发出相同的代码。

顺便说一句,如果您要采用 IEEE 格式,则无需在比较之前将其强制转换回浮动。IEEE 格式很漂亮:对于所有正有限值,a<b当且仅当reinterpret_cast<int_type>(a) < reinterpret_cast<int_type>(b)

  • “IEEE 格式很漂亮”——仅使用符号-数值整数表示。-0.5 &lt; -0.125 但 bf000000 &gt; be000000 (3认同)
  • 在 MSVC 上,您可以在函数之前添加“#pragma inside(fabs)”(即在全局范围内) (2认同)