CUDA内核不启动。

6
我的问题与这个很相似:链接。我运行了最简单的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()操作时,它没有返回任何错误。为什么内核无法启动?

1
我相信对于计算能力为2.0或更高的设备,您可以直接调用printf。并且您可能希望进行一些错误检查,以查看是否从调用中获得任何错误消息。 - Bart
参见:http://stackoverflow.com/questions/6565759/cuda-cuprintf-causes-unspecified-launch-failure - Paul R
1
还要注意你链接的问题中的第一个评论:http://stackoverflow.com/questions/9519272/cuda-kernel-not-launching - 你上面的代码完全没有错误检查 - 那些函数有返回状态,你知道的。 - Paul R
@Bart 好的,我现在使用printf,并删除了所有的cudaPrintf东西,但是内核还没有打印! - Tarek
3个回答

13
使用 printf 时没有输出的原因是,内核启动是异步的,并且在打印缓冲区刷新之前程序已经退出。CUDA(5.0)C编程指南的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();
} 

1
cudaPrintfDisplay 隐式同步上下文,因此这不是原始代码中的问题。 - talonmies
谢谢,我从我的答案中删除了最后一行,因此它不再表示其他内容。 - harrism

4
您确定您的CUDA设备支持SM_20架构吗?
请从nvcc命令行中删除arch=选项并重新编译所有内容。这将编译为1.0 CUDA架构,该架构将支持所有CUDA设备。如果仍无法运行,请进行清理并确保没有任何对象文件留在任何地方,然后重新构建和运行。
此外,arch=指的是虚拟架构,应该类似于compute_10。sm_20是真正的架构,我认为应该与code=开关一起使用,而不是arch=。

谢谢。我将其删除后,内核使用cuPrintf最终打印出来了。 - Tarek
我现在记得我一开始必须使用“-arch=sm_20”,因为我对浮点变量执行了atomicAdd操作,而这不能在sm_10上完成。有没有其他选择? - Tarek
2
了解您的硬件能力。运行不受硬件支持的代码是困难的。;> - dthorpe

0

在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;

为所有这些架构生成代码会使您的代码变慢。 因此,逐个排除以找出哪些 computesm 生成的代码是您的GPU所需的。 但是,如果您要将此发送给其他人,请最好包括所有这些。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接