Existe-t-il une manière intelligente de réduire le nombre de l if statements
dans le noyau d'un CUDA ?
J'écris une application qui calculera un Hamiltonien à plusieurs corps (simulation d'un système quantique). Les calculs dépendent fortement de conditional expressions
.
La raison pour laquelle je veux réduire ces instructions est qu'elles introduisent une surcharge de performance. (entier warp
saisit chaque option de if(){} else if(){}
si la condition n'est pas remplie, la thread
pour un temps donné, reste inactif).
Question :
1. Will switch()
La déclaration résout le problème ?
2. Le code ci-dessous est destiné à représenter une idée générale :
class tag_option_1 {};
class tag_option_2 {};
class tag_option_3 {};
template<typename T> __device__
int cal_something(int ab, int cd)
{
return -12345; // error value. default case is an error.
};
template<> __device__
int cal_something<tag_option_1>(int ab, int cd)
{
// return something
}
template<> __device__
int cal_something<tag_option_2>(int ab, int cd)
{
// return something
}
template<> __device__
int cal_something<tag_option_3>(int ab, int cd)
{
// return something
}
////////////////////////////////
// version #1:
__global__
void calc_hamiltonian(int * foo, int * bar)
{
unsigned int tid = /* calce thread index*/;
// do something...
if (/* condition */)
{
cal_something<tag_option_1>(foo[tid], bar[tid]);
}
else if(/* condition */)
{
cal_something<tag_option_2>(foo[tid], bar[tid]);
}
else if(/* condition */)
{
cal_something<tag_option_3>(foo[tid], bar[tid]);
}
// no default case.
// do something...
}
////////////////////////////////
// version #2:
// "magical" way to select a version:
// variant is meant to be something like "boost::variant" but implementented without a single "if" statement.
// This "magical" step is meant to be resolved at compile time.
__devcie__
variant <tag_option_1, tag_option_2, tag_option_3>
version_selector(int ab, int cd)
{
// magic happens here.
}
__global__
void calc_hamiltonian(int * foo, int * bar)
{
unsigned int tid = /* calce thread index*/;
// do something...
cal_something <version_selector(foo[tid], bar[tid])> (foo[tid], bar[tid]);
// do something...
}
Existe-t-il un moyen d'implémenter un version #2
de l'exemple ci-dessus, ou bien il est impossible en CUDA C/C++
?