最近我正在使用一个应用程序,其代码类似于:
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/