Я работаю над гамма-функцией, которая генерирует 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;
}
Есть ли способ, которым я могу оптимизировать этот код?
Вы можете избежать трубопроводные киоски устраняя разветвление на Input<1.0f && Input>0.0f
если набор команд поддерживает арифметика насыщенности или используйте макс / мин встроенные, например, 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 () в плавающей точке