【问题标题】:CUDA memory transfer issueCUDA 内存传输问题
【发布时间】:2012-10-31 14:48:55
【问题描述】:

我正在尝试执行一个代码,该代码首先将数据从 CPU 传输到 GPU 内存,反之亦然。尽管数据量增加,但数据传输时间保持不变 好像没有实际发生数据传输。我正在发布代码。

#include <stdio.h>  /* Core input/output operations                         */
#include <stdlib.h> /* Conversions, random numbers, memory allocation, etc. */
#include <math.h>   /* Common mathematical functions                        */
#include <time.h>   /* Converting between various date/time formats         */
#include <cuda.h>   /* CUDA related stuff                                   */
#include <sys/time.h>
__global__ void device_volume(float *x_d,float *y_d)
{
    int index = blockIdx.x * blockDim.x + threadIdx.x;
}

int main(void)
{
    float *x_h,*y_h,*x_d,*y_d,*z_h,*z_d;
    long long  size=9999999;
    long long nbytes=size*sizeof(float);

    timeval t1,t2;
    double et;

    x_h=(float*)malloc(nbytes);
    y_h=(float*)malloc(nbytes);

    z_h=(float*)malloc(nbytes);

    cudaMalloc((void **)&x_d,size*sizeof(float));
    cudaMalloc((void **)&y_d,size*sizeof(float));
    cudaMalloc((void **)&z_d,size*sizeof(float));
    gettimeofday(&t1,NULL);

    cudaMemcpy(x_d, x_h, nbytes, cudaMemcpyHostToDevice);
    cudaMemcpy(y_d, y_h, nbytes, cudaMemcpyHostToDevice);
    cudaMemcpy(z_d, z_h, nbytes, cudaMemcpyHostToDevice);

    gettimeofday(&t2,NULL);
    et = (t2.tv_sec - t1.tv_sec) * 1000.0;      // sec to ms
    et += (t2.tv_usec - t1.tv_usec) / 1000.0;   // us to ms
    printf("\n %ld\t\t%f\t\t",nbytes,et);
    et=0.0;
    //printf("%f %d\n",seconds,CLOCKS_PER_SEC); 

    // launch a kernel with a single thread to greet from the device
    //device_volume<<<1,1>>>(x_d,y_d);
    gettimeofday(&t1,NULL);

    cudaMemcpy(x_h, x_d, nbytes, cudaMemcpyDeviceToHost);
    cudaMemcpy(y_h, y_d, nbytes, cudaMemcpyDeviceToHost);
    cudaMemcpy(z_h, z_d, nbytes, cudaMemcpyDeviceToHost);

    gettimeofday(&t2,NULL);

    et = (t2.tv_sec - t1.tv_sec) * 1000.0;      // sec to ms
    et += (t2.tv_usec - t1.tv_usec) / 1000.0;   // us to ms
    printf("%f\n",et);
    cudaFree(x_d);
    cudaFree(y_d);
    cudaFree(z_d); 
    return 0;
}

谁能帮我解决这个问题?

谢谢

【问题讨论】:

  • 我相信cudaMemcpy 是异步的——在收集第二个时间戳之前,您至少需要运行一个虚拟内核。
  • 嗯,cudaMemcpy 是同步的,而 cudaMemcpyAsync 是异步的变体。我已经在不同的 C1050 特斯拉 GPU 上测试了这段代码,它工作得很好。但是使用不同的 GTX 250,它不会给出正确的结果。
  • OK - 我所说的异步是指一旦启动 DMA 传输,调用就会返回,因此传输要等到一段时间后才能完成。然后调用内核将阻塞,直到任何挂起的 DMA 传输完成。尝试添加一个虚拟内核,看看是否有帮助。
  • 顺便说一句,您最好使用 cuda 事件 API 来为 cuda 操作计时。一些 cuda 操作是异步的,并且会给出令人费解的计时结果,因为它们可能几乎立即将控制权转移回 CPU 线程。但是对于这种情况,我最好的猜测是你也应该做 cuda 错误检查。您可能根本没有传输任何数据,因为 GPU 由于某种原因不可用。我编译并运行了你的代码,得到了 28 和 76,大小为 9999999,当我将大小更改为 99999 时,我得到了 0.54 和 0.84。如果您想要最快的传输,请使用 cudaHostAlloc 进行调查。
  • Paul R,不,cudaMemcpy() 不是 异步的。在 memcpy 完成之前它不会返回。顾名思义,CUDA中的异步memcpy称为cudaMemcpyAsync()。请注意,尽管 cudaMemcpyAsync() 需要固定主机内存。

标签: cuda gpu


【解决方案1】:
  1. 尝试使用 cudaEvent 来捕获 GPU 代码的时间。
  2. 尝试使用 Visual profiler 查看在 memcpy 上花费了多少时间。分析器将显示每个 cuda 相关操作在 GPU 上花费的所有执行时间。

【讨论】:

    【解决方案2】:

    它保持不变,因为它需要相同的时间。在您的代码中,您不会将传输时间相加。

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 2016-12-18
      • 2011-08-24
      • 2016-03-14
      • 1970-01-01
      • 2014-08-14
      • 2013-07-26
      • 2020-04-04
      • 2015-03-26
      相关资源
      最近更新 更多