CUDA:cudaEventElapsedTime返回设备未就绪错误

时间:2011-07-01 17:14:18

标签: cuda

我试图测量特斯拉(T10处理器)上的经过时间,并且cudaEventElapsedTime返回设备未就绪错误。但是当我在Fermi(特斯拉M2090)上进行测试时,它给了我结果。

任何人都可以告诉我发生了什么......

这是我的代码

cudaError_t err;
        cudaEvent_t start, stop;
        cudaEventCreate(&start);
        cudaEventCreate(&stop);
        err = cudaEventRecord(start, 0);
        f(err != cudaSuccess) {
          printf ("\n\n 1. Error: %s\n\n", cudaGetErrorString(err));
          exit(1);
        }
        // actual code
       cudaThreadSynchronize();
        err = cudaEventRecord(stop, 0);
        if(err != cudaSuccess) {
          printf ("\n\n2. Error: %s\n\n", cudaGetErrorString(err));
          exit(1);
        }
        err = cudaEventElapsedTime(&elapsed_time, start, stop);
        f(err != cudaSuccess) {
          printf ("\n\n 3. Error: %s\n\n", cudaGetErrorString(err));
          exit(1);
        }

2 个答案:

答案 0 :(得分:5)

这是因为cudaEventRecord是异步的。无论状态如何,它都会立即完成执行。异步函数只是在“CUDA执行队列”上下订单。当GPU完成当前分配时,它会弹出下一个订单并执行它。这一切都在一个单独的线程中完成,由CUDA驱动程序处理,与程序主机线程分开。

cudaEventRecord是一个或多或少说这样的命令:“当你完成以前的所有工作时,请在这个变量中标记我。”

如果您的主机线程然后要求cudaEventElapsedTime,但GPU尚未完成其工作,则会感到困惑并报告“尚未准备就绪!”。 cudaEventSynchronize()停止当前主机线程,直到GPU达到您之前放置的cudaEventRecord顺序。在此之后,您可以保证cudaEventElapsedTime将为您提供有意义的答案。

cudaThreadSynchronize()只是一个更强大的工具:它会停止当前线程,直到GPU完成所有分配的任务,而不仅仅是那些直到事件。

答案 1 :(得分:0)

即使我遇到了这个问题,因此根据@CygnusX1 的回答,我将所有执行代码保存在一个单元格中,而将 cudaEventElapsedTime 保存在另一个单元格中。这解决了这个问题,因为 Colab(或 jupyter notebook)只有在当前单元格中的过程完成后才会转到下一个单元格。

因此,

with torch.no_grad():
  model.eval() # warm up
  model(x)
  start.record() 
  model(x)
  model(x)
  model(x)
  end.record()
  print('execution time in MILLISECONDS: {}'.format(start.elapsed_time(end)/3.0))

提出问题中报告的错误,即 device not ready error 并由

解决
with torch.no_grad():
  model.eval()
  model(x) # warm up
  start.record() 
  model(x)
  model(x)
  model(x)
  end.record()
# Shift the print command to next code CELL !!!
 print('execution time in MILLISECONDS: {}'.format(start.elapsed_time(end)/3.0))