我有一个问题。我想让我的用户选择在哪个GPU上运行。所以我在我的机器上进行测试,这台机器只有一个GPU(设备0),如果他们选择了不存在的设备,会发生什么。
如果我执行cudaSetDevice(0);
它将正常工作。
如果我执行:cudaSetDevice(1);
它将崩溃并显示invalid device ordinal
(我可以处理它,因为该函数返回一个错误)。
如果我执行:cudaSetDevice(0); cudaSetDevice(1);
它将崩溃并显示invalid device ordinal
(我可以处理它,因为该函数返回一个错误)。
然而! 如果我执行:cudaSetDevice(1); cudaSetDevice(0);
第二条命令将返回成功,但当我尝试在我的GPU上计算第一次时,它将崩溃并显示invalid device ordinal
。我无法处理此问题,因为第二条命令没有返回任何错误!
对我来说,第一个cudaSetDevice似乎留下了一些东西,影响了第二个命令?
非常感谢!
解决方案:(感谢Robert Crovella!)。我之前处理错误的方法是:
error = cudaSetDevice(1);
if (error) { blabla }
显然,在调用cudaSetDevice(1)之后需要调用cudaGetLastError(),否则错误消息不会从某些错误堆栈中删除,而且稍后在我为另一个函数执行cudaGetLastError()时会崩溃,尽管此时没有错误。
cudaPeekAtLastError()
,它 不会 清除错误代码。每次你要求它返回最后一个错误(比如,在你的内核启动后)。相反地,cudaGetLastError()
将清除它返回的错误(即,如果没有新的错误发生,未来的检查将不再返回那个错误,而是返回cudaSuccess
)。这与API返回的错误代码不同。如果你想让内核启动不失败,在非法的cudaSetDevice(1)
调用之后的某个地方做cudaGetLastError
即可。 - Robert CrovellacudaPeekAtLastError
。你的问题中缺乏明确的示例,这使得任何人都很难回答。 - Robert Crovella