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

2023-12-10

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

请看下面我的表现:

Copy 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.

我希望复制时间应该独立于分配矩阵值所需的内部迭代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

EDIT: 附加信息 :

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 GPU 复制到 CPU 比将 CPU 复制到 GPU 慢 的相关文章

随机推荐