我有一个大数组(图像),我需要对这些数据进行许多小的可配置计算。我将在这里发布一个例子。注意:这不是实际的问题,而是我需要做的一个最小的/希望能说明问题的例子。
// 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语句的影响?
您可以将选择要使用的适当函数的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/elses在编译时?
此外,这个问题可能会引起人们的兴趣:使用函数指针剪切if语句会更有效吗?
只要参数是const
OR,编译器就可以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>);
}
}
也许有类似的东西
#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 );
}
}