【问题标题】:Setting up Visual Studio Intellisense for CUDA kernel calls为 CUDA 内核调用设置 Visual Studio Intellisense
【发布时间】:2011-08-29 00:39:49
【问题描述】:

我刚刚开始进行 CUDA 编程,一切顺利,我的 GPU 已被识别,一切正常。我已经使用这个非常有用的指南在 Visual Studio 中部分设置了 Intellisense: http://www.ademiller.com/blogs/tech/2010/10/visual-studio-2010-adding-intellisense-support-for-cuda-c/

这里: http://www.ademiller.com/blogs/tech/2011/05/visual-studio-2010-and-cuda-easier-with-rc2/

但是,Intellisense 仍然无法接收这样的内核调用:

// KernelCall.cu
#include <iostream>
#include "cuda.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

__global__ void kernel(void){}

int main()
{
    kernel<<<1,1>>>();

    system("pause");
    return 0;
}

行 kernel>>() 带有红色下划线,特别是第一个箭头左侧的一个箭头,错误为“错误:预期和表达式”。但是,如果我将鼠标悬停在函数上,它的返回类型和参数会正确显示。它仍然编译得很好,我只是想知道如何摆脱这个小烦恼。

【问题讨论】:

    标签: visual-studio-2010 cuda intellisense gpu


    【解决方案1】:

    哇,这个线程上有很多灰尘。我想出了一个宏修复(好吧,更像是解决方法......),我想我会分享:

    // nvcc does not seem to like variadic macros, so we have to define
    // one for each kernel parameter list:
    #ifdef __CUDACC__
    #define KERNEL_ARGS2(grid, block) <<< grid, block >>>
    #define KERNEL_ARGS3(grid, block, sh_mem) <<< grid, block, sh_mem >>>
    #define KERNEL_ARGS4(grid, block, sh_mem, stream) <<< grid, block, sh_mem, stream >>>
    #else
    #define KERNEL_ARGS2(grid, block)
    #define KERNEL_ARGS3(grid, block, sh_mem)
    #define KERNEL_ARGS4(grid, block, sh_mem, stream)
    #endif
    
    // Now launch your kernel using the appropriate macro:
    kernel KERNEL_ARGS2(dim3(nBlockCount), dim3(nThreadCount)) (param1); 
    

    我更喜欢这种方法,因为由于某种原因,我的代码中总是丢失 '

    【讨论】:

    【解决方案2】:

    Visual Studio 为 C++ 提供 IntelliSense,火箭科学家博客中的技巧基本上是依靠 CUDA-C 与 C++ 的相似性,仅此而已。

    在 C++ 语言中,正确解析尖括号是很麻烦的。 &lt; 是 less than 和 for 模板,&lt;&lt; 是 shift,记得不久前我们不得不在嵌套模板声明之间放置一个空格。

    所以事实证明,提出这种语法的 NVIDIA 人并不是语言专家,并且碰巧选择了最糟糕的分隔符,然后将它翻了三倍,好吧,你会遇到麻烦的。令人惊奇的是,Intellisense 在看到这一点时完全可以工作。

    我知道在 CUDA 中获得完整 IntelliSense 的唯一方法是从运行时 API 切换到驱动程序 API。 C++ 只是 C++,而 CUDA 仍然是(有点)C++,语言解析没有 &lt;&lt;&lt;&gt;&gt;&gt; 不好的地方。

    【讨论】:

    • 我必须说,你比 NVIDIA 论坛上的任何人都更有道理......那我该怎么做你刚才说的呢?
    • 看看matrixMul和matrixMulDrv的区别。 >> 语法由编译器处理,本质上只是吐出调用驱动程序 API 调用的代码。您将链接到 cuda.lib 而不是 cudart.lib,如果您仅使用 CUDA-RT 库,则可能必须处理“混合模式”程序。
    • 在我的博客上查看我对您问题的回复。蜘蛛是正确的。这不太可能正常工作。
    • 感谢您的帮助,我最想知道这是否是预期的行为,这基本上让我放心。再次感谢。
    • 更新:2021。如果您 #include "cuda_runtime.h" 并将 CUDA 包含添加到您的包含路径中,Visual Studio 2019 的表现相当不错。在我的机器上它是 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.2\include
    【解决方案3】:

    从 VS 2015 和 CUDA 7 开始,您可以在任何其他包含之前添加这两个包含,前提是您的文件具有 .cu 扩展名:

    #include "cuda_runtime.h"
    #include "device_launch_parameters.h"
    

    不需要宏或任何东西。之后一切都会完美运行。

    【讨论】:

    • 在错误列表中选择“仅构建”以消除“预期表达式”错误
    • 在 VS 2019 上为我工作。我唯一的问题:需要 #include "cuda_runtime.h" 吗?只需#include "device_launch_parameters.h",我的简单测试看起来就很好。
    • 错误?你是说红线?能举个例子吗?
    • 在 VS2019 社区上添加这些行似乎对我也不起作用。 @BartDeBoeck 这只是过滤错误列表,而不是突出显示。
    • 是的,这并不能解决我在 VS2017 中的 Intellisense 问题
    【解决方案4】:

    我喜欢Randysolution。我将使用 C 预处理器可变参数宏进行匹配和提升:

    #ifdef __INTELLISENSE__
    #define CUDA_KERNEL(...)
    #else
    #define CUDA_KERNEL(...) <<< __VA_ARGS__ >>>
    #endif
    

    用法示例:

    my_kernel1 CUDA_KERNEL(NUM_BLOCKS, BLOCK_WIDTH)();
    my_kernel2 CUDA_KERNEL(NUM_BLOCKS, BLOCK_WIDTH, SHMEM, STREAM)(param1, param2);
    

    【讨论】:

      【解决方案5】:

      我一直在学习 CUDA 并遇到了这个确切的问题。正如其他人所说,这只是 Intellisense 问题,可以忽略,但我找到了一个干净的解决方案,实际上将其删除。

      如果 >> 在模板函数中,它似乎被解释为正确的代码。

      当我想为内核创建包装器以便能够从常规 cpp 代码中调用它们时,我偶然发现了它。它既是一个很好的抽象,又消除了语法错误。

      内核头文件(例如kernel.cuh)

      const size_t THREADS_IN_BLOCK = 1024;
      
      typedef double numeric_t;
      
      // sample kernel function headers
      __global__ void sumKernel(numeric_t* out, numeric_t* f, numeric_t* blockSum, size_t N);
      __global__ void expKernel(numeric_t* out, numeric_t* in, size_t N);
      // ..
      
      // strong-typed wrapper for a kernel with 4 arguments
      template <typename T1, typename T2, typename T3, typename T4>
      void runKernel(void (*fun)(T1, T2, T3, T4), int Blocks, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { 
          fun <<<Blocks, THREADS_IN_BLOCK >>> (arg1, arg2, arg3, arg4);
      }
      
      // strong-typed wrapper for a kernel with 3 arguments
      template <typename T1, typename T2, typename T3>
      void runKernel(void (*fun)(T1, T2, T3), int Blocks, T1 arg1, T2 arg2, T3 arg3) { 
          fun <<<Blocks, THREADS_IN_BLOCK >>> (arg1, arg2, arg3);
      }
      
      // ...
      
      // the one-argument fun cannot have implementation here
      void runKernel(void (*fun)(), int Blocks);
      

      在 .cu 文件中(您会在此处遇到语法错误,但您是否需要无参数内核函数?如果不需要,可以删除此文件和相应的头文件):

      void runKernel(void (*fun)(), int Blocks) { 
          fun <<<Blocks, THREADS_IN_BLOCK >>> ();
      }
      

      .cpp 文件中的用法:

      runKernel(kernelFunctionName, arg1, arg2, arg3);
      // for example runKernel(expKernel, B, output, input, size);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-01
        • 1970-01-01
        • 2012-04-26
        • 2023-03-21
        • 2021-06-14
        相关资源
        最近更新 更多