cudaMemcpyAsync一定是异步的吗?

参考代码:

#include <iostream>
#include <device_launch_parameters.h>
#include <cuda_runtime.h>
#include <string.h>
#include <assert.h>

#define N 1048576

__global__ void MyKernel(int *p0, int n)
{
    int i = threadIdx.x + blockIdx.x * blockDim.x;
    if (i < n)
    {
        p0[i] = 1;
    }
}

#define CUDA_CALL(x) {const cudaError_t a = (x); if (a != cudaSuccess) { printf("\nCUDA \
Error: %s (err_num¼%d) \n", cudaGetErrorString(a), a); cudaDeviceReset(); assert(0);} }

// #define USE_MALLOC_HOST

int main(void)
{

    int* p0;
    long nbytes = sizeof(int) * N;

#ifdef USE_MALLOC_HOST
    CUDA_CALL(cudaMallocHost((void**)&p0, nbytes));
#else
    p0 = new int[N];
#endif
    memset(p0, 0, nbytes);

    int* devp0;
    // GPU端分配内存
    CUDA_CALL(cudaMalloc((void**)&devp0, nbytes));

    dim3 dimBlock(1024);
    dim3 dimGrid(N/1024);

    // 执行kernel
    cudaStream_t stm;
    CUDA_CALL(cudaStreamCreate(&stm));

    MyKernel<<<dimGrid, dimBlock, 0, stm>>>(devp0, N);
    // 将在GPU端计算好的结果拷贝回CPU端
    CUDA_CALL(cudaMemcpyAsync(p0, devp0, nbytes, cudaMemcpyDeviceToHost, stm));

    // 理论上,cudaMemcpyAsync是异步的,下面的断言会失败,但实际上。。。
    assert(p0[0] == 1);
    assert(p0[N/3] == 1);
    assert(p0[N/3*2] == 1);
    assert(p0[N-1] == 1);

    cudaStreamDestroy(stm);
    cudaFree(devp0);
#ifdef USE_MALLOC_HOST
    cudaFreeHost((void*)p0);
#else
    delete[] p0;
#endif
}

理论上,cudaMemcpyAsync是异步的,所以assert会失败。
但上面的代码运行却不会出错:


image.png

如果把上面代码中的USE_MALLOC_HOST宏打开,编译运行:


image.png

这次失败了。
所以看起来,当通过cudaMemcpyAsync从GPU拷贝数据到CPU时,如果目的地的host memory是new/malloc出来的,调用是同步的;如果host memory是cudaMallocHost出来的,则才真是异步的。
下面在nsys-ui中看看两种情况下的区别(要先把代码中的assert注释掉,不能让进程dump掉)。
  1. host memory为new/malloc的情况


    image.png

    从图中可以看出,cudaMemcpyAsync返回的时候,HW中的Memcpy已经结束了。

  2. host memory为cudaMallocHost的情况


    image.png

    从图中可以看出,基本上cudaMemcpyAsync返回后,HW中的Memcpy才开始工作。

官方文档说明见:CUDA Runtime API :: CUDA Toolkit Documentation (nvidia.com)
“For transfers from device memory to pageable host memory, the function will return only once the copy has completed.”这句话似乎也说明,从GPU拷贝数据到CPU上new/malloc出来的memory,是同步的。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. 知识准备 1.1 中央处理器(CPU) 中央处理器(CPU,Central Processing Unit)...
    贰爷阅读 5,670评论 0 2
  • 开篇一张图,后面听我编 1. 知识准备 1.1 中央处理器(CPU) 中央处理器(CPU,Central Proc...
    He_Yu阅读 47,450评论 7 115
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 6,081评论 0 12
  • 史上最全的iOS面试题及答案 迷途的羔羊--专为路痴量身打造的品牌。史上最精准的定位。想迷路都难!闪电更新中......
    南虞阅读 5,414评论 0 8
  • ———————————————回答好下面的足够了---------------------------------...
    恒爱DE问候阅读 5,678评论 0 4