为CUDA内核调用设置VS 2010 Intellisense

时间:2011-05-19 16:08:33

标签: visual-studio-2010 cuda intellisense gpu-programming

我刚刚开始进行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;
}

行内核&lt;&lt;&lt;&lt;&lt;&gt;&gt;&gt;()用红色下划线,特别是第一个箭头左侧的一个箭头,错误显示为“Error:expected and expression”。但是,如果我将鼠标悬停在该函数上,则会正确显示其返回类型和参数。它仍然编译得很好,我只是想知道如何摆脱这个小烦恼。

5 个答案:

答案 0 :(得分:25)

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

// 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)
#end

// Now launch your kernel using the appropriate macro:
kernel KERNEL_ARGS2(dim3(nBlockCount), dim3(nThreadCount)) (param1); 

我更喜欢这种方法,因为出于某种原因,我总是失去'&lt;&lt;&lt;&lt;&lt;在我的代码中,但宏通过语法着色获得了一些帮助:)。

答案 1 :(得分:13)

Visual Studio为C ++提供了IntelliSense,来自火箭科学家博客的技巧基本上依赖于CUDA-C对C ++的相似性,仅此而已。

在C ++语言中,正确解析尖括号很麻烦。你有<小于和{和模板',<<作为移位,记得不久前我们不得不在嵌套模板声明之间放置一个空格。

事实证明,NVIDIA的那个提出这种语法的人并不是语言专家,碰巧选择了最差的分隔符,然后将它增加了三倍,好吧,你将遇到麻烦。令人惊讶的是Intellisense在看到它时会发挥作用。

我知道在CUDA中获得完整IntelliSense的唯一方法是从Runtime API切换到Driver API。 C ++只是C ++,而CUDA仍然是(有点)C ++,语言解析没有<<<>>>的不良,需要解决。

答案 2 :(得分:7)

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

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

不需要MACROS或任何东西。之后一切都会完美无缺。

答案 3 :(得分:0)

我一直在学习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);

答案 4 :(得分:0)

我喜欢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);