我刚刚开始 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/
但是,智能感知仍然无法接收这样的内核调用:
// 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;
}
内核<<<1,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);
我更喜欢这种方法,因为出于某种原因,我总是丢失代码中的"<<<",但宏通过语法着色:)获得一些帮助。
Visual Studio为C++提供了IntelliSense,火箭科学家博客的诀窍基本上是依赖于CUDA-C必须C++的相似性,仅此而已。
在C++语言中,正确解析尖括号很麻烦。模板的<
小于和小于模板,<<
shift 的,请记住不久前,我们必须在嵌套模板声明之间放置一个空格。
所以事实证明,NVIDIA提出这种语法的人不是语言专家,碰巧选择了最糟糕的分隔符,然后将其增加了三倍,好吧,你会有麻烦的。令人惊讶的是,当Intellisense看到这一点时,它完全可以工作。
我知道在 CUDA 中获得完整智能感知的唯一方法是从运行时 API 切换到驱动程序 API。C++只是C++,而 CUDA 仍然(有点)C++,语言解析没有<<<>>>
坏处。
从 VS 2015 和 CUDA 7 开始,您可以在任何其他包含之前添加这两个包含,前提是您的文件具有.cu
扩展名:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
不需要宏或任何东西。之后一切都会完美运行。
兰迪的解决方案。我将使用 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);
在学习 CUDA 并遇到了确切的问题。正如其他人所说,这只是智能感知问题,可以忽略不计,但我找到了一个干净的解决方案,实际上可以删除它。
如果<<<>>>位于模板函数内,则似乎被解释为正确的代码。
当我想为内核创建包装器以便能够从常规 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);