为啥在内核启动之前开始数据迁移(D 到 H)?

Posted

技术标签:

【中文标题】为啥在内核启动之前开始数据迁移(D 到 H)?【英文标题】:Why data migration (D to H) started before kernel launch?为什么在内核启动之前开始数据迁移(D 到 H)? 【发布时间】:2022-01-07 03:37:30 【问题描述】:

以下是基于 CUDA 托管内存的代码的 nvvp 分析结果:

问题: 如上面的屏幕截图所示,数据迁移(D 到 H)甚至在内核启动之前就开始了。尽管与需要传输的总数据(大约 4 MB)相比,第一个数据迁移块(在内核启动之前开始)的大小非常小(大约 450kb)。那么,这些数据究竟是什么?如何在发布前进行数据迁移(D 到 H)?

我的代码:

#include <iostream>
#include <math.h>

#include "device_launch_parameters.h"
#include "cuda_runtime.h"

// CUDA kernel to add elements of two arrays
__global__
void add(int n, float* x, float* y)

    int index = blockIdx.x * blockDim.x + threadIdx.x;
    int stride = blockDim.x * gridDim.x;
    for (int i = index; i < n; i += stride)
        y[i] = x[i] + y[i];



int RunManagedVersion()

    int N = 1 << 20;
    float* x, * y;

    // Allocate Unified Memory -- accessible from CPU or GPU
    cudaMallocManaged(&x, N * sizeof(float));
    cudaMallocManaged(&y, N * sizeof(float));

    // initialize x and y arrays on the host
    for (int i = 0; i < N; i++) 
        x[i] = 1.0f;
        y[i] = 2.0f;
    

    // Launch kernel on 1M elements on the GPU
    int blockSize = 256;
    int numBlocks = (N + blockSize - 1) / blockSize;
    add << <numBlocks, blockSize >> > (N, x, y);

    // Wait for GPU to finish before accessing on host
    cudaDeviceSynchronize();

    // Check for errors (all values should be 3.0f)
    float maxError = 0.0f;
    for (int i = 0; i < N; i++)
        maxError = fmax(maxError, fabs(y[i] - 3.0f));

    std::cout << "Max error: " << maxError << std::endl;

    // Free memory
    cudaFree(x);
    cudaFree(y);

    return 0;


int main()

    //RunUnmanagedVersion();

    RunManagedVersion();

    return 0;

【问题讨论】:

【参考方案1】:

分析器不会将这种类型的 D->H 转移定位到特定的时间点。

相反,它将时间线分成大致固定的时间段,并确定在该段期间是否发生了任何 D->H 传输。如果是这样,则该段将被报告为“其中”有 D->H 传输,并且该段将用颜色编码以指示该段内传输的相对“密度”。

因此,您所指的绿色条的开头不一定是发生 D->H 转移的时刻,而是发生某些 D->H 转移活动的测量段的开始.

由于绿色条在内核完成后很好地延伸,显然是内核完成后 D->H 传输活动的原因,这是预期的。

(可以在内核启动之前、期间和之后就 H->D 线和蓝条提出类似的问题。显然不需要 H->D 活动之后 内核启动。同样,根据固定的时间段测量和报告活动。)

顺便说一下(对于未来的读者),在内核启动之前的数据迁移 (D->H) 已在here 进行了解释。

【讨论】:

谢谢,我也认为时间线不能准确表示数据传输的实际开始/停止,但想确认我没有遗漏任何东西。

以上是关于为啥在内核启动之前开始数据迁移(D 到 H)?的主要内容,如果未能解决你的问题,请参考以下文章

windows内核为啥不是文件

如何在内核中获取当前时间(UTC

为啥这段 Java 代码没有利用所有 CPU 内核?

为啥我在运行 Python 时在 Spyder 中收到“启动内核时发生错误”?

为啥允许我运行块数超过 GPU 的 CUDA 核心数的 CUDA 内核?

如何将 DolphinDB 集群迁移到另一台机器上