我有一个大型数组(图像),我需要对该数据进行许多小的可配置计算。 我将在这里发布一个例子。 注意:这不是实际问题,而是我需要做的最小/希望说明的例子。
// 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语句的影响?
答案 0 :(得分: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?
此问题可能也很有趣: Is cutting if statements by using function pointers going to be more efficient?
答案 1 :(得分:2)
只要参数为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>);
}
}
答案 2 :(得分: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 );
}
}