关于 printf:cuda 11 内核不运行

cuda 11 kernel doesn't run

这里是一个 demo.cu,旨在从 GPU 设备打印 f:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include"cuda_runtime.h"
#include"device_launch_parameters.h"

#include <stdio.h>

__global__ void hello_cuda() {
        printf("hello from GPU\
");
}

int main() {
        printf("hello from CPU\
");
        hello_cuda <<<1, 1>>> ();
        cudaDeviceSynchronize();

        cudaDeviceReset();
        printf("bye bye from CPU\
");
        return 0;
}

编译并运行:

1
2
$ nvcc demo.cu
$ ./a.out

这是我得到的输出:

1
2
hello from CPU
bye bye from CPU

问:为什么GPU没有打印结果?

这似乎是因为我错误地配置了 cuda 工具包或其他东西,但是我能够从 cuda-samples 编译和运行各种程序。例如,matrixMul 或 deviceQuery


如果您的设备具有 3.0 或更低的计算能力,CUDA 11 将不再支持这些 GPU。您需要使用以前的 CUDA 版本。

CUDA 编译器必须针对 GPU 目标(即设备架构)进行编译。如果没有在编译命令行中指定目标架构,历史上,CUDA 选择了一个非常灵活的默认架构规范,可以在 CUDA 版本支持的所有 GPU 上运行。

但情况并非总是如此,CUDA 11 也并非如此。CUDA 11 编译为默认架构 sm_52(计算能力 5.2,即好像您在命令上指定了 -arch=sm_52线)。但 CUDA 11 支持低至 sm_35 的架构(计算能力 3.5)。

因此,如果您没有在 CUDA 11 的编译命令行上指定目标架构,并尝试在具有早于 sm_52 的架构的 GPU 上运行,那么您编写的任何 CUDA 代码(内核)肯定会赢不行。

这是一种很好的做法,当您在使用 CUDA 代码时遇到问题时,使用正确的 CUDA 错误检查,如果您在此处执行此操作,您将获得一个运行时错误指示,该指示会立即识别问题(至少对于熟悉 CUDA 错误的人)。

在这些情况下,解决方案是指定一个编译命令,其中包含您打算在其上运行的 GPU(这通常是一种很好的做法)。如果您这样做,并且您指定的架构"已弃用",那么 nvcc 编译器将发出警告,让您知道未来的 CUDA 版本可能不支持您尝试运行的 GPU。该警告并不意味着您所做的任何事情都是错误或非法的或需要更改,但它意味着将来,未来的 CUDA 版本可能不支持该 GPU。

如果你想抑制那个警告,你可以通过编译命令行上的 -Wno-deprecated-gpu-targets 开关。

当然,同样的问题也可能出现在 Windows 上。在这种情况下,您需要修改以下 VS 项目设置以匹配您设备的架构:

enter