Optimization CUDA中的编译时信息

Optimization CUDA中的编译时信息,optimization,cuda,Optimization,Cuda,我正在优化一个时间非常关键的CUDA内核。我的应用程序接受影响行为的各种开关(例如,是使用三阶导数还是五阶导数)。把一组50个开关看作一个近似值,每个开关是一个整数变量(有时是布尔值,或者是浮点,但这种情况与这个问题不太相关)。 在应用程序执行期间,所有这些开关都是恒定的。大多数开关都是运行时的,我将它们存储在恒定内存中,以便利用缓存机制。其他一些开关可以是编译时的,如果客户希望更改开关中的值,则可以重新编译应用程序。一个非常简单的例子是: __global__ void mykernel(co

我正在优化一个时间非常关键的CUDA内核。我的应用程序接受影响行为的各种开关(例如,是使用三阶导数还是五阶导数)。把一组50个开关看作一个近似值,每个开关是一个整数变量(有时是布尔值,或者是浮点,但这种情况与这个问题不太相关)。 在应用程序执行期间,所有这些开关都是恒定的。大多数开关都是运行时的,我将它们存储在恒定内存中,以便利用缓存机制。其他一些开关可以是编译时的,如果客户希望更改开关中的值,则可以重新编译应用程序。一个非常简单的例子是:

__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_this
do_
是计算绑定的,并且非常便宜,我优化了
for
循环,使其开销可以忽略不计,我必须将
if
放在迭代中。如果编译器认识到
compile\u time\u开关
是静态信息,它可以优化对“错误”函数的调用,并创建与If不存在一样优化的代码。现在真正的问题是:

我可以通过哪些方式向编译器提供此开关的静态值?我看到下面列出的两种方法,但它们都不适合我。还有什么其他可能性


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

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);
}
现在
GlobalParameters::compile_time_switch
包含我想要的静态信息,并且编译器能够优化内核。不幸的是,CUDA不支持这种静态成员

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


我认为我的问题由于这个事实和克罗诺斯的回答而解决了。但是,我仍在寻找其他替代方法来向编译器提供编译时信息。

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

#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 comand line开关指定定义,并且(我认为)任何受nvidia支持的编译器都将接受-D(msvc可能使用不同的开关)。

好的,是的,谢谢分享。实际上,这是我们目前的解决方案。我们试图避免过多地利用预处理器,因为它会降低代码的可读性,此外,我们希望编译时和运行时开关都有类似的机制,即,从用户的角度来看,开关是编译时还是运行时应该尽可能透明(用户=读取开关的程序员)@Spiros-Yves-Daoust对我的帖子做了一些编辑。这些更改增加了代码的可读性。哦,是的,当然你可以这样使用宏。因此,总而言之,使用预处理器是一个有效的选择。我仍在寻找其他可能的方法来指定编译时信息,以便编译器可以优化死代码。
#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);
}