繁体   English   中英

从 GPU 复制到 CPU 比将 CPU 复制到 GPU 慢

[英]copy from GPU to CPU is slower than copying CPU to GPU

我开始学习cuda有一段时间了,我有以下问题

在下面看看我是怎么做的:

复制 GPU

int* B;
// ...
int *dev_B;    
//initialize B=0

cudaMalloc((void**)&dev_B, Nel*Nface*sizeof(int));
cudaMemcpy(dev_B, B, Nel*Nface*sizeof(int),cudaMemcpyHostToDevice);
//...

//Execute on GPU the following function which is supposed to fill in 
//the dev_B matrix with integers


findNeiborElem <<< Nblocks, Nthreads >>>(dev_B, dev_MSH, dev_Nel, dev_Npel, dev_Nface, dev_FC);

再次复制CPU

cudaMemcpy(B, dev_B, Nel*Nface*sizeof(int),cudaMemcpyDeviceToHost);
  1. 将数组 B 复制到 dev_B 只需几分之一秒。 但是将数组 dev_B 复制回 B 需要很长时间。
  2. findNeiborElem 函数涉及每个线程的循环,例如它看起来像这样

    __ global __ void findNeiborElem(int *dev_B, int *dev_MSH, int *dev_Nel, int *dev_Npel, int *dev_Nface, int *dev_FC){ int tid=threadIdx.x + blockIdx.x * blockDim.x; while (tid<dev_Nel[0]){ for (int j=1;j<=Nel;j++){ // do some calculations B[ind(tid,1,Nel)]=j// j in most cases do no go all the way to the Nel reach break; } tid += blockDim.x * gridDim.x; } }

非常奇怪的是,将 dev_B 复制到 B 的时间与 j 索引的迭代次数成正比。

例如,如果Nel=5则时间约为5 sec

当我增加Nel=20 ,时间约为20 sec

我希望复制时间应该独立于需要分配 Matrix dev_B值的内部迭代。

此外,我希望从 CPU 复制相同矩阵的时间和向 CPU 复制相同矩阵的时间顺序相同。

你知道有什么问题吗?

您应该使用事件而不是使用 clock() 来测量时间:

有了事件,你会有这样的事情:

  cudaEvent_t start, stop;   // variables that holds 2 events 
  float time;                // Variable that will hold the time
  cudaEventCreate(&start);   // creating the event 1
  cudaEventCreate(&stop);    // creating the event 2
  cudaEventRecord(start, 0); // start measuring  the time

  // What you want to measure
  cudaMalloc((void**)&dev_B, Nel*Nface*sizeof(int));
  cudaMemcpy(dev_B, B, Nel*Nface*sizeof(int),cudaMemcpyHostToDevice);

  cudaEventRecord(stop, 0);                  // Stop time measuring
  cudaEventSynchronize(stop);               // Wait until the completion of all device 
                                            // work preceding the most recent call to cudaEventRecord()

  cudaEventElapsedTime(&time, start, stop); // Saving the time measured

编辑:附加信息:

“内核启动在完成之前将控制权返回给 CPU 线程。因此,您的计时结构正在测量内核执行时间以及第二个 memcpy。在内核之后对副本计时时,您的计时器代码将立即执行,但是cudaMemcpy 正在等待内核在启动之前完成。这也解释了为什么您对数据返回的计时测量似乎因内核循环迭代而异。它还解释了为什么花在内核函数上的时间“可以忽略不计”。 归功于罗伯特·克罗维拉

至于你的第二个问题

 B[ind(tid,1,Nel)]=j// j in most cases do no go all the way to the Nel reach

在 GPU 上执行计算时,由于同步原因,每个完成工作的线程都不会执行任何计算,直到同一工作组中的所有线程都完成。

换句话说,您执行此计算所需的时间将是最坏情况下的时间,如果大多数线程没有一路下降也没关系。

我不确定你的第一个问题,你如何衡量时间? 我对 cuda 不太熟悉,但我认为当从 CPU 复制到 GPU 时,实现会缓冲您的数据,隐藏所涉及的有效时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM