当CPU尝试读取GPU初始化的托管内存时,为什么数据会从主机迁移到设备?

问题描述

在以下测试代码中,我们通过GPU初始化数据,然后通过cpu访问数据。我对nvprof的分析结果有2个问题。

  • 为什么只有一个数据从主机迁移到设备?以我的理解,它应该是“设备到主机”。

  • 为什么H-> D计数为2?我认为应该为1,因为数据在一页中。

谢谢!

我的环境

  • 驱动程序版本:418.87.00
  • CUDA版本:10.1
  • ubuntu 18.04
#include <cuda.h>
#include <iostream>

using namespace std;

__global__ void setVal(char* data,int idx)
{
    data[idx] = 'd';
}


int main()
{
    const int count =  8;

    char* data;
    cudamallocManaged((void **)&data,count);

    setVal<<<1,1>>>(data,0); //GPU page fault

    cout<<" cpu read " << data[0] <<endl; 
  
    cudaFree(data);

    return 0;
}
==28762== Unified Memory profiling result:
Device "GeForce GTX 1070 (0)"
   Count  Avg Size  Min Size  Max Size  Total Size  Total Time  Name
       2  32.000KB  4.0000KB  60.000KB  64.00000KB  11.74400us  Host To Device
       1         -         -         -           -  362.9440us  Gpu page fault groups
Total cpu Page faults: 1

解决方法

为什么有一种数据从主机迁移到设备?以我的理解,应该是“设备到主机”。

您正在破坏主机和设备之间的数据。因为GPU内核启动是异步的,所以您的主机代码在内核启动后 发出,实际上是在GPU代码之前访问数据。

在内核调用之后放入cudaDeviceSynchronize(),以便在内核完成后 ,CPU代码才尝试读取数据。

您没有其他问题的答案。探查器通常无法完全解决非常少量的活动。它不一定在分析运行期间检测所有SM,并且其某些结果可能会根据GPC,TPC和/或整个GPU的大小进行缩放。那只是我的猜测,尽管只是猜测。在剖析几乎不执行任何操作的代码时,通常我不希望Profiler获得完全准确的结果。