c++ - std::fabs() 优化不好?

标签 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
}

这是在图形渲染循环中,调用速度约为 50-100 次/秒,多个 channel 中的缓冲区高达 192kHz。所以有很多数据在最里面的循环中运行,分析表明这是一个热点。

我想到可以将 float 转换为整数并删除符号位,然后仅使用临时变量将其转换回来。它看起来像这样:

if ((const float &&)(*((int *)&temp) & ~0x80000000) > (const float &&)(*((int *)&hPoint) & ~0x80000000))
    hPoint = temp;

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

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

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

最佳答案

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

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

关于c++ - std::fabs() 优化不好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23490339/

相关文章:

c++ - 声明数组时 VS2008 错误预期常量表达式,但 GCC 中此代码没有错误

c - 可以使用位运算符检查数字是否在数组中

c - 位操作(从 X 中提取第 5 位并返回 X 中 1 位的数量)

c - 确定字节中的哪一位被设置

c - 使用按位运算符交换整数中的第一个和最后一个数字

c++ - GLFW 输入处理未按预期工作

c++ - 子目录中带有 protobuf 文件的 CMake

c++ - 如何从 swf 或 abc 文件生成 swc

c++ - 如何测试一个数字是否是 2 的幂?

c++ - 添加多个 QDockWidget