0

大きな配列 (画像) があり、そのデータに対して多くの小さな構成可能な計算を行う必要があります。ここに例を投稿します。 注:これは実際の問題ではありませんが、私がしなければならないことの最小限の/できれば例示的な例です。

// different functions that can be called based on the configuration
float func1( float* a )
{
    return (*a) * (*a);
}

float func2( float* a )
{
    return (*a) + (*a);
}

float func3( float* a )
{
    return 2 * (*a) * (*a);
}

// my data
float* data = new float[1024*1024];

// function that manages the configurations
int main(  )
{
    int param1 = 0;
    int param2 = 1;

    for ( int k = 0; k < 1024*1024; k++ )
    {
        if ( param1 == 2 && param2 == 0 )
            data[k] = func1( data + k );
        else if ( param1 == 1 && param2 == 1 )
            data[k] = func2( data + k );            
        else if ( param1 == 0 && param2 == 1 )
            data[k] = func3( data + k );
        else
            continue;

    }
}

私のコードでは、各関数内にループを配置しても意味がありません。

ただし、param1 と param2 はループ中に一定のままであり、コンパイル時に認識されます。

if/elseif ステートメントの影響を取り除く方法はありますか?

4

3 に答える 3

2

パラメーターが OR である限り、const変数がエイリアス化されていないため、変更されないことをコンパイラーが 100% 判断できる限り (コンパイラーにとってはより困難です)、オプティマイザーがランタイム ブランチを完全に削除し、すべての作業を実行することを完全に期待します。コンパイル時間。

ただし、オプティマイザーに依存したくない場合は、テンプレートを使用できます。

template <int c1, int c2>
float func(float* a)
{
    // No-op.
}

template <>
float func<2, 0>(float* a)
{
    return (*a) * (*a);
}

template <>
float func<1, 1>(float* a)
{
    return (*a) + (*a);
}

template <>
float func<0, 1>(float* a)
{
    return 2 * (*a) * (*a);
}

int main()
{
    const int param1 = 0;
    const int param2 = 1;

    for ( int k = 0; k < 1024*1024; k++ )
    {
        func<param1, param2>(<float ptr>);
    }
}
于 2015-03-19T17:55:07.143 に答える
2

使用する適切な関数を選択する if-else ステートメントをループの外に移動して、次のようにすることができます。

#include <functional>
// different functions that can be called based on the configuration
float func1( float* a )
{
    return (*a) * (*a);
}

float func2( float* a )
{
    return (*a) + (*a);
}

float func3( float* a )
{
    return 2 * (*a) * (*a);
}

// my data
float* data = new float[1024*1024];

// function that manages the configurations
int main(  )
{
    int param1 = 0;
    int param2 = 1;

    std::function< float( float* )> functionToUse = nullptr;

    if ( param1 == 2 && param2 == 0 )
        functionToUse = std::function<float(float*)>(func1);
    else if ( param1 == 1 && param2 == 1 )
        functionToUse = std::function<float(float*)>(func2);            
    else if ( param1 == 0 && param2 == 1 )
        functionToUse = std::function<float(float*)>(func3);

    if(functionToUse){
        for ( int k = 0; k < 1024*1024; k++ )
        {
            data[k] = functionToUse( data + k );
        }    
    }
}

コンパイル時に使用する関数の選択に関しては、次の質問をチェックすることをお勧めします: if/else at compile time?

また、この質問も興味深いかもしれません: 関数ポインターを使用して if ステートメントをカットすると、より効率的になりますか?

于 2015-03-19T14:48:27.333 に答える