很抱歉,如果之前有人问过这个问题,但我找不到这个确切的问题。
我有一个看起来像这样的模板化 CUDA 内核:
template<int firstTextureIndex, int secondTextureIndex, int thirdTextureIndex> __global__ void myKernel
三种纹理索引模板类型的范围为 0-7,直到运行时才知道。我需要实例化这个内核的所有 512 种组合,然后根据纹理索引的运行时值调用正确的模板。
我从来没有写过任何预处理宏,并且正在努力避免它。另一个帖子,here , 展示了如何通过这样做递归地为一个模板变量实例化多个 class 模板:
template<int i>
class loop {
loop<i-1> x;
}
template<>
class loop<1> {
}
loop<10> l;
我正在努力将它扩展到 3 个变量和一个函数(而不是一个类)以适应我的情况。即使我弄清楚如何以这种方式实例化所有这些,我如何在没有嵌套 switch 语句的情况下在运行时实际调用 512 种可能性中的 1 种?为了说明这一点,我试图避免的嵌套 switch 语句如下:
switch(firstTextureIndex)
{
case 0:
switch(secondTextureIndex)
{
case 1:
switch(thirdTextureIndex)
{
case 2:
myKernel<0, 1, 2><<<grid, block>>>(param1, param2, param3);
break;
}
break;
}
break;
}
如果我弄清楚如何为它们全部实例化 0-7,我可以这样调用它吗:
myKernel<i, j, k><<<grid, block>>>(param1, param2);
如果我让 i、j 和 k 枚举类型只包含 0-7?这样编译器就可以知道所有可能的值,并且由于我将它们全部实例化,所以它可以吗?
请注意,这个三重模板有充分的理由传递纹理索引,但为了简洁起见,我省略了解释。非常感谢任何有关实例化和/或调用此内核的帮助。
编辑:Jarod42 提供了一个有效的解决方案,完全符合我的要求。不幸的是,我现在意识到 c++ 标准在这里很重要。我正在使用 c++98/03 结合最新稳定版本的 boost 库,因此使用这些的解决方案将是理想的。我可能会使用 c++11,但由于我们的编译器的限制,c++14 已经过时了。
最佳答案
你可以这样做:
template <std::size_t I>
void do_job()
{
myKernel<I / 64, (I / 8) % 8, I % 8>{}();
}
template <std::size_t ... Is>
void callMyKernel(std::index_sequence<Is...>, std::size_t i, std::size_t j, std::size_t k)
{
std::function<void()> fs[] = {&do_job<Is>...};
fs[i * 64 + j * 8 + k]();
}
void callMyKernel(std::size_t i, std::size_t j, std::size_t k)
{
callMyKernel(std::make_index_sequence<512>{}, i, j, k);
}
关于c++ - 为模板参数的所有组合实例化函数,在运行时选择实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35562342/