我有一个CUDA(C ++)代码,它仅出于性能原因使用函数模板,因此该函数将只执行它需要做的事情,而不是经常加载和读取布尔值以检查是否需要执行某些操作
所有模板参数都是布尔值。在启动内核时,CPU会检查布尔值并启动相应的值,我相信它被称为内核模板的“实例化”。我理解这会给出指数代码大小的增长,但我的问题是关于其他事情:启动内核模板涉及2 ^ n if语句,是否有更聪明的语法?
例如,如果n = 2:
if(bool1){
if(bool2){
<true,true>func();
}
else{
<true,false>func();
}
}
else{
if(bool2){
<false,true>func();
}
else{
<false,false>func();
}
}
当n = 10时,它变得不可接受,是否有语法来避免这种恐怖?
例如我试过了
<bool1 ? true:false,bool2 ? true:false>func()
但是编译器不喜欢它......
Change boolean flags into template arguments似乎谈论了一个类似的问题,但是OP不仅仅是布尔,并且提供的解决方案对我来说看起来比问题更糟糕,坦率地说,我不明白它的一个词。
答案 0 :(得分:9)
你可以像这样添加func
的重载:
template< bool... Bs >
void func()
{
// Implement func with compile-time Bs...
}
template< bool... Bs, typename... Ts >
void func( bool b, Ts... ts )
{
if( b ) {
func< Bs..., true >( ts... );
}
else {
func< Bs..., false >( ts... );
}
}
int main()
{
// call func< true, false, true, true >();
func( true, false, true, true );
}
它的工作原理是将运行时布尔参数逐个转换为编译时参数。
答案 1 :(得分:2)
一旦你掌握了可变参数模板的扩展,这是相当简单的。
此代码使用3个二进制编译时选项构建函数的每个版本的向量。向量索引是将这些选项视为二进制位的整数值:
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
// the actual function implementation
template <bool option_a, bool option_b, bool option_c>
void function_with_options()
{
if(option_a)
cout << "option a is enabled, ";
else
cout << "no option a, ";
if(option_b)
cout << "option b is enabled, ";
else
cout << "no option b, ";
if(option_c)
cout << "option c is enabled, ";
else
cout << "no option c, ";
}
// convert an integer into the 3 option bits and return a corresponding function object
template<int bits>
std::function<void()>
make_function_with_options()
{
return function_with_options<bool(bits & 1), bool(bits & 2), bool(bits & 4)>;
}
// expand an index sequence of make_function_with_options<int>
template<size_t... Is>
std::vector<std::function<void()>>
make_all_functions_impl(std::index_sequence<Is...>)
{
auto v = std::vector<std::function<void()>> { make_function_with_options<Is>()... };
return v;
}
// make an ordered vector of the 8 function variants
std::vector<std::function<void()>>
make_all_functions()
{
return make_all_functions_impl(make_index_sequence<8>{});
}
// here is my global 'switch'
static const std::vector<std::function<void()>> bit_functions = make_all_functions();
int main()
{
// call each 'switch' option to prove it works
for(size_t i = 0 ; i < bit_functions.size() ; ++i)
{
cout << "case " << i << " ";
bit_functions[i]();
cout << endl;
}
return 0;
}
输出:
case 0 no option a, no option b, no option c,
case 1 option a is enabled, no option b, no option c,
case 2 no option a, option b is enabled, no option c,
case 3 option a is enabled, option b is enabled, no option c,
case 4 no option a, no option b, option c is enabled,
case 5 option a is enabled, no option b, option c is enabled,
case 6 no option a, option b is enabled, option c is enabled,
case 7 option a is enabled, option b is enabled, option c is enabled,
答案 2 :(得分:0)
将每个布尔值编码为数字中的一位,然后使用switch语句。像这样设置位:
int i = 0;
i = i | ((1 << (N-1)) && boolN);