为啥用Visual Studio给CUDA编程,却显示"undeclared identifier"呢

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥用Visual Studio给CUDA编程,却显示"undeclared identifier"呢相关的知识,希望对你有一定的参考价值。

为什么用Visual Studio给CUDA编程,却显示"undeclared identifier",我已经包含了cuda.h,为什么他还是不能识别命令?(注意我不是在问那段英文什么意思),以下是我的代码
include<cuda.h>

int main()
float *a = new float[N*N];
float *b = new float[N*N];
float *c = new float[N*N];
for ( int i = 0; i < N*N; ++i )
a[i] = 1.0f; b[i] = 3.5f;
float *ad, *bd, *cd;
const int size = N*N*sizeof(float);
cudaMalloc( (void**)&ad, size );
cudaMalloc( (void**)&bd, size );
cudaMalloc( (void**)&cd, size );
cudaMemcpy( ad, a, size, cudaMemcpyHostToDevice );
cudaMemcpy( bd, b, size, cudaMemcpyHostToDevice );
dim3 dimBlock( blocksize, blocksize );
dim3 dimGrid( N/dimBlock.x, N/dimBlock.y );
add_matrix<<<dimGrid, dimBlock>>>( ad, bd, cd, N );
cudaMemcpy( c, cd, size, cudaMemcpyDeviceToHost );
cudaFree( ad ); cudaFree( bd ); cudaFree( cd );
delete[] a; delete[] b; delete[] c;
return EXIT_SUCCESS;


const int N = 1024;
const int blocksize = 16;
__global__
void add_matrix( float* a, float *b, float *c, int N )

int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
int index = i + j*N;
if ( i < N && j < N )
c[index] = a[index] + b[index];

参考技术A include<cuda.h>
少了个“#”,另外,最好使用双引号,应该是:
#include "cuda.h"追问

加上了,还是不行

追答

const int N = 1024;
const int blocksize = 16;
这两个应该放在main函数前面

如果还有错误,你把错误发出来,看看是哪一行出错的

追问

还是不行,每一行都有错,dudaMalloc,cudaMemcpy,dudafree等等,常用的命令都不能识别,另外,build rule用的是runtime API 4.0.

追答

#include "cuda_runtime.h"

追问

还是不行

为 CUDA 内核调用设置 Visual Studio Intellisense

【中文标题】为 CUDA 内核调用设置 Visual Studio Intellisense【英文标题】:Setting up Visual Studio Intellisense for CUDA kernel calls 【发布时间】: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>>() 带有红色下划线,特别是第一个箭头左侧的一个箭头,错误为“错误:预期和表达式”。但是,如果我将鼠标悬停在函数上,它的返回类型和参数会正确显示。它仍然编译得很好,我只是想知道如何摆脱这个小烦恼。

【问题讨论】:

【参考方案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); 

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

【讨论】:

感谢您的出色解决方案。此外,不是“#end”而是“#endif”是对的。对小事感到抱歉。 似乎__INTELLISENSE____CUDACC__ 更安全,检查***.com/a/6182137/8037585 和devtalk.nvidia.com/default/topic/513485/… 这是一个有用的解决方案,但非常难看。希望微软修改 Intellisense,以便不再需要像这样的解决方案【参考方案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】:

我喜欢Randy 的solution。我将使用 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);

【讨论】:

以上是关于为啥用Visual Studio给CUDA编程,却显示"undeclared identifier"呢的主要内容,如果未能解决你的问题,请参考以下文章

基于Visual Studio 2015的CUDA编程:基本配置

基于Visual Studio 2015的CUDA编程:基本配置

为啥用visual studio2012编程时输入汉字显示为问号

Visual Studio 是不是使用 nvcc 编译 cuda 代码?

为啥我的Visual Studio 2010 运行时不能显示汉字?

Visual Studio Nsight“Cuda Toolkit V7.5 目录不存在”错误