我有以下代码:
template <int size>
inline uint hashfn( const char* pStr )
{
uint result = *pStr;
switch ( size )
{
case 10:
result *= 4;
result += *pStr;
case 9:
result *= 4;
result += *pStr;
...
...
case 2:
result *= 4;
result += *pStr;
}
return result;
}
此代码是某些长度的DNA序列的哈希函数,其中长度是模板参数。它是一个展开的循环,带有一个switch语句,可以在正确的位置跳转。 然而,大小是常量,因为它是模板参数。 我可以将它专门用于某些尺寸值吗? 也许有类似的东西:
template <int 2>
inline uint hashfn( const char* pStr )
{
uint result = *pStr;
result *= 4;
++pStr;
result += *pStr;
return result;
}
答案 0 :(得分:3)
我倾向于使用模板递归地进行。
E.g。 :
template<class TOp,int factor>
struct recursive_unroll {
__forceinline static void result( TOp& k ) {
k();
recursive_unroll<TOp,factor-1>::result( k );
}
};
template<class TOp>
struct recursive_unroll<TOp,0> {
__forceinline static void result( TOp& k ) {}
};
struct op {
op( const char* s ) : res( 0 ), pStr( s ) {}
unsigned int res;
const char* pStr;
__forceinline void operator()() {
res *= 4;
res += *pStr;
++pStr;
//std::cout << res << std::endl;
}
};
char str[] = "dasjlfkhaskjfdhkljhsdaru899weiu";
int _tmain(int argc, _TCHAR* argv[])
{
op tmp( str );
recursive_unroll<op,sizeof( str ) >::result( tmp );
std::cout << tmp.res << std::endl;
return 0;
}
这为我提供了最佳代码。如果没有 __ forceinline ,代码就没有正确内联。
在使用此类优化之前,您应始终对代码进行测试。然后你应该看一下程序集并破译你的编译器已经为你做的事情。但在这种情况下,它似乎是一种推动力(对我而言)。
__ forceinline 是Microsoft Visual Studio特定的扩展程序。编译器应该生成最佳代码,但为此它不会。所以我在这里使用了这个扩展名。
答案 1 :(得分:1)
请阅读有关维基百科上的循环展开的信息。重点是保存循环变量的比较。你有没有对代码进行分析?与循环相比,我没有看到这样可以如何节省周期。
任何现代编译器都应该完全展开一个带有小静态循环计数的循环。
我也希望你不要使用基于模数的哈希表的哈希值,因为你将丢失哈希值的高位。
答案 2 :(得分:0)
原始代码中没有涉及循环,因此无法展开。
答案 3 :(得分:0)
你可以像这样专攻。但是,我认为您正专注于展开循环的优化。在您分析代码并显示它是瓶颈之前,最好不要过早地优化代码。
答案 4 :(得分:0)
我有以下代码:...(使用Duff设备的代码)......
这是一个展开的循环,带有一个switch语句,可以在正确的位置跳转。然而,大小是常量,因为它是模板参数。我可以针对某些尺寸值进行专门化吗?
你当然可以,但每种可能的尺寸都会涉及很多样板。通过适当的抽象级别,以及使用Boost metaprogramming和preprocessor库,您甚至可以将其归结为合理的。
您的维护成本会上升,所以我会回应其他人并建议您确保 这样做可以。
答案 5 :(得分:0)
我不知道语义是否正确,但在这种情况下,函数模板本身可以是递归的:
template <int size>
inline uint hashfn( const char* pStr ) {
uint result = *pStr;
result *= 4;
return result + hashfn<size-1>(++pStr);
}
//case 0 stops
template <>
inline uint hashfn<0>( const char* pStr ) {
return 0;
}
正如克里斯托弗所说,只要确保它被内联......
答案 6 :(得分:0)
代码
template <size_t N>
void
function (float *a, float *b, float *c)
{
for (size_t i = 0; i < N; ++i)
{
c[i] = a[i] * b[i];
}
}
我的编译器(msvc 2005,gcc 4.3)自动展开循环。