Как я могу оптимизировать эту функцию 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() в плавающей точке

Другие вопросы по тегам