我试图测量特斯拉(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);
}
答案 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))