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

只要参数是constOR,编译器就可以 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 回答
0

也许是这样的

#include <iostream>
#include <map>
#include <functional>
#include <utility>

typedef std::pair<size_t, size_t> pair;
typedef std::map< pair, std::function<float( float* )>> map;

// 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];

void init( map &myMap )
{
    myMap.insert( pair, std::function<float( float* )>>
                ( pair( 2, 0 ), std::function< float( float* )>( func1 ) ) );
    myMap.insert( pair, std::function<float( float* )>>
                ( pair( 1, 1 ), std::function< float( float* )>( func2 ) ) );
    myMap.insert( pair, std::function<float( float* )>>
                ( pair( 0, 2 ), std::function< float( float* )>( func3 ) ) );
}

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

    map myMap;

    init( myMap );

    for( int k = 0; k < 1024 * 1024; k++ )
    {
        data[k] = myMap[pair( param1, param2 )]( data + k );
    }
}
于 2015-03-19T14:42:55.317 回答