CUDA中的编译时信息

时间:2014-03-10 09:51:42

标签: optimization cuda

我正在优化一个非常时间关键的CUDA内核。我的应用程序接受影响行为的各种开关(例如,是否使用3阶或5阶导数)。考虑作为近似的一组50个开关,其中每个开关都是一个整数变量(有时是bool,或浮点数,但这种情况与此问题不太相关)。

在执行应用程序期间,所有这些开关都是常量。大多数这些开关都是运行时,我将它们存储在常量内存中,因此要利用缓存机制。其他一些开关可以是编译时间,如果客户想要更改交换机中的值,则必须重新编译应用程序。一个非常简单的例子可能是:

__global__ void mykernel(const float* in, float *out)
{
    for ( /* many many times */ )
        if (compile_time_switch)
            do_this(in, out);
        else
            do_that(in, out);
}

假设do_thisdo_that是计算限制且非常便宜的,我优化for循环以使其开销可以忽略不计,我必须放置{{1}在迭代中。如果编译器认识到if是静态信息,它可以优化对“错误”函数的调用,并创建与if不存在时一样优化的代码。现在真正的问题是:

我可以在哪些方面为编译器提供此开关的静态值?我看到下面列出的两种方式,但它们都不适用于我。还有其他可能性吗?


模板参数

提供模板参数可启用此静态优化。

compile_time_switch

这个简单的解决方案对我不起作用,因为我无法直接访问调用内核的代码。

静态成员

考虑以下结构:

template<int compile_time_switch>
__global__ void mykernel(const float* in, float *out)
{
    for ( /* many many times */ )
        if (compile_time_switch)
            do_this(in, out);
        else
            do_that(in, out);
}

现在struct GlobalParameters { static const bool compile_time_switch = true; }; 包含我想要的静态信息,并且编译器能够优化内核。不幸的是,CUDA不支持这样的静态成员。

编辑:最后一句话显然是错误的。结构的定义当然是合法的,您可以在设备代码中使用静态成员GlobalParameters::compile_time_switch。编译器内联变量,因此最终代码将直接包含值,而不是运行时变量访问,这是您期望从优化器编译器获得的行为。所以,第二种选择实际上是合适的。

我认为我的问题既解决了这个问题,也解决了kronos的问题。但是,我仍然在寻找其他替代方法来为编译器提供编译时信息。

1 个答案:

答案 0 :(得分:2)

您的第三个选项是预处理器定义:

#define compile_time_switch 1

__global__ void mykernel(const float* in, float *out)
{
    for ( /* many many times */ )
        if (compile_time_switch)
            do_this(in, out);
        else
            do_that(in, out);
}

预处理器将完全丢弃else情况,并且编译器在其死代码终止传递中没有任何优化,因为没有死代码。

此外,您可以使用-D命令行开关指定定义,并且(我认为)任何由nvidia支持的编译器都会接受-D(msvc可能使用不同的开关)。