CUDA - 子网格将在哪个流中?

Posted

技术标签:

【中文标题】CUDA - 子网格将在哪个流中?【英文标题】:CUDA - Which stream will child grid be in? 【发布时间】:2022-01-14 03:03:33 【问题描述】:

如果我使用动态并行,子网格将在哪个流中运行?

例如,我有一个叫A的内核,另一个叫B的内核。B是由A启动的。

如果内核 A 在 stream_A 中运行,并且如果我没有为内核 B 指定流 ID,内核将在哪个流中运行?它是默认流,还是会继承 A 正在运行的流?

【问题讨论】:

【参考方案1】:

根据我在文档中看到的内容以及我自己的实验,我观察到通常主机上的流和设备上的流之间没有(排序)关系。

我们可以考虑两种情况:

第一种情况,对于创建的流,我会说这是覆盖explicitly in the documentation。

在第二种情况下,虽然文档提到了设备 NULL 流,但这可能有点不清楚。我们可以编写一个简单的测试用例来为我们解决这个问题:

$ cat cdp.cu
#include <cstdio>
#include <cassert>
#include <unistd.h>
const unsigned long long dt = 10000000000ULL;
__device__ void delay()
        unsigned long long start = clock64();
        while (start+dt > clock64());

__global__ void child()
        delay();

__global__ void parent()
        child<<<1,1>>>();
        cudaError_t err = cudaGetLastError();
        assert(err == cudaSuccess);
        err = cudaDeviceSynchronize();
        assert(err == cudaSuccess);

__global__ void pk()
        printf("hello\n");

int main()
        cudaStream_t s1, s2;
        cudaStreamCreate(&s1);
        cudaStreamCreate(&s2);
        parent<<<1,1, 0, s1>>>();
        sleep(1);
        pk<<<1,1,0,s2>>>();
        cudaDeviceSynchronize();

$ nvcc -o cdp cdp.cu -rdc=true -lcudadevrt -lineinfo
$ time ./cdp                 
hello

real    0m7.276s
user    0m4.193s
sys     0m2.061s
$

(Ubuntu 18.04、CUDA 11.4、V100)

当我运行上述代码时,我观察到在启动 cdp 可执行文件后,控制台保持空闲大约 1 秒。之后控制台打印“hello”,然后控制台保持空闲 6-7 秒,然后应用程序退出。 (请不要期望在 WDDM GPU 中出现相同的行为。)

如果设备上的 NULL 流与主机上的 NULL 流“相同”或“继承自”,那么我们预计“hello”打印输出直到应用程序退出前才会出现。如果涉及主机 NULL 流语义,则在 child 内核完成之前,不允许运行 pk 内核。因此我们必须得出结论,设备 NULL 流与主机 NULL 流不同。

我们可以使用一点逻辑来说服自己,这与继承用于parent 内核启动的主机(创建)流也不完全相同。我们可以在文档中读到,在同一个线程块中使用 NULL 流启动子内核将具有 NULL 流行为。但是,如果设备 NULL 流与主机创建的流完全相同/继承自主机创建的流,则这不可能是真的。根据文档,如果我有两个子内核从同一个线程块启动,一个进入 NULL 流,另一个进入设备创建的流,那么我们不希望它们能够同时运行——这就是空流。但是,如果 NULL 流只是继承的主机流,即创建的流,则没有理由期望它们不能同时运行。

所以我们得出结论,设备 NULL 流不是主机 NULL 流,设备 NULL 流也不是主机创建的流。这些陈述在我看来与文档一致。

如果您想在文档中得到澄清,通常的建议是file a bug。

与其担心 NULL 流行为的特殊性,我在教授 CUDA 时给出的建议是,如果您担心复杂的并发场景,请使用已创建的流来完成所有工作。留下 NULL 流。您想做的任何事情都可以完全使用创建的流来完成。当然,随心所欲。

【讨论】:

以上是关于CUDA - 子网格将在哪个流中?的主要内容,如果未能解决你的问题,请参考以下文章

CUDA笔记(一)线程与数据量的关系

排序子网格/VBO

使用 CUDA 进行矩阵乘法:2D 块与 1D 块

CUDA 内核的参数

在内核上工作的 CUDA 上的向量

子网划分的CIDR