Как я могу оптимизировать эту функцию S-кривой?
Я работаю над гамма-функцией, которая генерирует "S-кривую". Мне нужно запустить его в среде реального времени, поэтому мне нужно максимально ускорить его.
Код выглядит следующим образом:
float Gamma = 2.0f; //Input Variable
float GammaMult = pow(0.5f, 1.0f-Gamma);
if(Input<1.0f && Input>0.0f)
{
if(Input<0.5f)
{
Output = pow(Input,Gamma)*GammaMult;
}
else
{
Output = 1.0f-pow(1.0f-Input,Gamma)*GammaMult;
}
}
else
{
Output = Input;
}
Есть ли способ, которым я могу оптимизировать этот код?
2 ответа
Вы можете избежать остановок конвейера, устраняя ветвление на Input<1.0f && Input>0.0f
если набор инструкций поддерживает арифметику насыщения или использует значения max/min, например, x86 MAXSS
Вы также должны устранить другие ответвления путем округления насыщенного Input
, Полный алгоритм:
float GammaMult = pow(0.5f, 1.0f-Gamma);
Input = saturate(Input); // saturate via assembly or intrinsics
// Input is now in [0, 1]
Rounded = round(Input); // round via assembly or intrinsics
Coeff = 1 - 2 * Rounded
Output = Rounded + Coeff * pow(Rounded + Coeff * Input,Gamma)*GammaMult;
Округление должно быть сделано также через asm/intrinsics.
Если вы используете эту функцию, например, для последовательных значений массива, вам следует рассмотреть возможность ее векторизации, если целевая архитектура поддерживает SIMD.
Ваш код кажется в порядке. Узким местом, если оно существует, является pow
функция. Единственное решение состоит в том, чтобы пойти немного глубже в детали низкого уровня и попытаться реализовать свой собственный pow
функция. Например, если вам достаточно 2-х чисел с плавающей запятой, вы можете найти некоторые основанные на приближении алгоритмы, которые работают быстрее.
Смотрите это: самый эффективный способ реализации функции pow() в плавающей точке