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
好吧,您将浮点模式设置为符合 IEEE 标准。通常,使用类似的开关--fast-math编译器之类的开关可以忽略 IEEE 极端情况,例如 NaN、INF 和非正规值。如果编译器也使用内在函数,它可能会发出相同的代码。
顺便说一句,如果您要采用 IEEE 格式,则无需在比较之前将其强制转换回浮动。IEEE 格式很漂亮:对于所有正有限值,a<b当且仅当reinterpret_cast<int_type>(a) < reinterpret_cast<int_type>(b)