【问题标题】:CUDA kernel doesn't launchCUDA 内核无法启动
【发布时间】:2012-08-23 06:06:46
【问题描述】:

我的问题很像one。我运行最简单的 CUDA 程序,但内核没有启动。但是,我确信我的 CUDA 安装没问题,因为我可以毫无问题地运行由多个文件(我从其他人那里获取)组成的复杂 CUDA 项目。在这些项目中,编译和链接是通过带有很多标志的 makefile 完成的。我认为问题在于编译时使用的正确标志。我只是使用这样的命令: nvcc -arch=sm_20 -lcudart test.cu 有这样一个程序(在linux机器上运行):

 __global__ void myKernel() 
{ 

    cuPrintf("Hello, world from the device!\n"); 


} 
int main() 
{ 
    cudaPrintfInit(); 
    myKernel<<<1,10>>>(); 
    cudaPrintfDisplay(stdout, true);    
    cudaPrintfEnd(); 
} 

程序编译正确。当我添加 cudaMemcpy() 操作时,它不会返回任何错误。关于内核为什么不启动的任何建议?

【问题讨论】:

  • 我相信对于计算能力 2.0 或更高版本的设备,您可以直接致电printf。您可能需要进行一些错误检查,看看是否从您的调用中收到任何错误消息。
  • 还要注意您链接到的问题中的第一条评论:stackoverflow.com/questions/9519272/cuda-kernel-not-launching - 您上面的代码绝对没有错误检查 - 这些函数返回状态是有原因的,您知道。
  • @Bart 好的,我现在用printf,把cudaPrinf的东西都去掉了,内核还没有打印出来!

标签: cuda gpgpu gpu


【解决方案1】:

使用printf 时不打印的原因是内核启动是异步的,并且您的程序在 printf 缓冲区被刷新之前退出。 CUDA (5.0) C Programming Guide 的 B.16 节对此进行了解释。

printf() 的输出缓冲区在内核启动之前设置为固定大小(请参阅 关联的主机端 API)。它是循环的,如果在内核期间产生更多的输出 执行超出缓冲区,旧的输出将被覆盖。它只被冲洗 当执行这些操作之一时:

  • 通过 >> 或 cuLaunchKernel() 启动内核(在启动开始时,如果 CUDA_LAUNCH_BLOCKING 环境变量设置为 1,在启动结束时为 好),
  • 通过 cudaDeviceSynchronize()、cuCtxSynchronize() 同步, cudaStreamSynchronize()、cuStreamSynchronize()、cudaEventSynchronize()、 或 cuEventSynchronize(),
  • 通过任何阻塞版本的 cudaMemcpy*() 或 cuMemcpy*() 复制内存,
  • 通过 cuModuleLoad() 或 cuModuleUnload() 加载/卸载模块,
  • 通过 cudaDeviceReset() 或 cuCtxDestroy() 销毁上下文。

因此,这个程序什么也不打印:

#include <stdio.h>

__global__ void myKernel() 
{ 
  printf("Hello, world from the device!\n"); 
} 

int main() 
{ 
  myKernel<<<1,10>>>(); 
} 

但是这个程序打印了十次“Hello, world from the device!\n”。

#include <stdio.h>

__global__ void myKernel() 
{ 
  printf("Hello, world from the device!\n"); 
} 

int main() 
{ 
  myKernel<<<1,10>>>(); 
  cudaDeviceSynchronize();
} 

【讨论】:

  • cudaPrintfDisplay 隐式同步上下文,所以这不是原始代码中的问题。
  • 谢谢,我从我的答案中删除了最后一行,所以它不再表明其他情况。
【解决方案2】:

您确定您的 CUDA 设备支持 SM_20 架构吗?

从您的 nvcc 命令行中删除 arch= 选项并重建所有内容。这为 1.0 CUDA 架构编译,所有 CUDA 设备都支持该架构。如果它仍然没有运行,请进行构建清理并确保没有任何目标文件遗留在任何地方。然后重建并运行。

另外,arch= 指的是虚拟架构,应该类似于 compute_10。 sm_20 是真正的架构,我认为应该与 code= 开关一起使用,而不是 arch=。

【讨论】:

  • 谢谢。我删除了它并最终使用 cuPrintf 打印了内核。
  • 我现在记得我必须首先使用'-arch=sm_20',因为我对浮点变量执行 atomicAdd 操作,而这不能使用 sm_10 完成。有没有其他选择?
  • 找出您的硬件的能力。很难运行硬件不支持的代码。 ;>
【解决方案3】:

在 Visual Studio 中:

右键单击您的项目 > 属性 > Cuda C/C++ > 设备

然后将以下内容添加到代码生成字段

compute_30,sm_30;compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75;

为所有这些架构生成代码会使您的代码变慢一些。所以一一排除,找出你的GPU需要哪个compute和sm生成代码。 但是,如果您要将其运送给其他人,最好包括所有这些。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-28
    • 2013-07-15
    • 1970-01-01
    • 2018-05-29
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多