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

9
我尝试在特斯拉(T10处理器)上测量经过的时间,但cudaEventElapsedTime返回设备未准备好错误。但是当我在费米(特斯拉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);
        }

我找到了这个问题的解决方案,但如果有人能告诉我为什么会发生这种情况,那就太好了。所以我会保持这个问题的开放性。解决方案是将cudaThreadSynchronize()放在cudaEventRecord(stop,0)之后。如果有人知道原因以及为什么在Fermi上没有发生,请告诉我。 - veda
3个回答

8
这是因为cudaEventRecord是异步的。它会立即完成执行,而不管状态如何。异步函数只是在“CUDA执行队列”上放置一个命令。当GPU完成当前任务时,它会弹出下一个命令并执行它。所有这些都在由CUDA驱动程序处理的单独线程中完成,与您的程序主机线程无关。 cudaEventRecord是一条命令,大致意思是:“当您完成所有先前的工作后,请在这个变量中标记我”。
如果您的主机线程然后要求cudaEventElapsedTime,但GPU尚未完成其工作,它会感到困惑并报告“尚未准备好!”cudaEventSynchronize()会阻塞当前主机线程,直到GPU达到您先前放置的cudaEventRecord命令。之后,您可以确保cudaEventElapsedTime将为您提供有意义的答案。 cudaThreadSynchronize()只是更强大的工具:它会阻塞当前线程,直到GPU完成所有分配的任务,而不仅仅是直到事件为止的任务。

谢谢。但是为什么费米架构没有遇到这个问题呢?我的意思是同样的代码在费米架构上成功运行并给出结果。为什么会这样呢? - veda
1
不知道。也许 Fermi 足够快了? :) - CygnusX1

0

我也遇到了这个问题,所以根据@CygnusX1的答案,我将所有的执行代码放在一个单元格中,而将cudaEventElapsedTime放在另一个单元格中。这解决了这个问题,因为Colab(或jupyter笔记本)只有在当前单元格的进程完成后才会转到下一个单元格。

因此,

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))

引发了问题中报告的错误,即设备未就绪错误,并已解决。

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))

0

如果您来自于PyTorch,并且遇到了这个错误:

-- Process 0 terminated with the following error:
Traceback (most recent call last):
  File "/home/user/anaconda3/lib/python3.9/site-packages/torch/multiprocessing/spawn.py", line 69, in _wrap
    fn(i, *args)
  File "/home/user/projects/ai/mlcrap/fsdp/FSDB_mnist.py", line 159, in fsdp_main
    print(f"CUDA event elapsed time: {init_start_event.elapsed_time(init_end_event) / 1000}sec")
  File "/home/user/anaconda3/lib/python3.9/site-packages/torch/cuda/streams.py", line 208, in elapsed_time
    return super().elapsed_time(end_event)
RuntimeError: CUDA error: device not ready

解决方法是这样同步 CUDA:
# (before)
init_start_event.record()
for epoch in range(1, args.epochs + 1):
    train(args, model, rank, world_size, train_loader, optimizer, epoch, sampler=sampler1)
    test(model, rank, world_size, test_loader)
    scheduler.step()

init_end_event.record()
torch.cuda.synchronize() # <---- ADD THIS LINE

print(f"CUDA event elapsed time: {init_start_event.elapsed_time(init_end_event) / 1000}sec")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接