Недавно я работал с приложением, имеющим код, похожий на:
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 раз/сек с буферами до 192 кГц в нескольких каналах. Так что много данных, проходящих через самые внутренние циклы, и профилирование показали, что это горячая точка.
Мне пришло в голову, что можно было поместить float в целое число и стереть бит знака и отбросить его, используя только временные. Это выглядело примерно так:
if ((const float &&)(*((int *)&temp) & ~0x80000000) > (const float &&)(*((int *)&hPoint) & ~0x80000000))
hPoint = temp;
Это дало 12-кратное сокращение времени рендеринга, при этом все же выдавая тот же действительный результат. Обратите внимание, что все в аудиодатах предварительно очищается, чтобы не включать nans/infs/denormals и иметь только диапазон [-1, 1].
Есть ли какие-либо угловые случаи, когда эта оптимизация даст неправильные результаты - или, почему стандартная функция библиотеки не реализована так? Я предполагаю, что это связано с обработкой ненормальных значений?
e: макет модели с плавающей точкой соответствует ieee, а sizeof (float) == sizeof (int) == 4