CUDA:无效设备序号

12

我有一个问题。我想让我的用户选择在哪个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()时会崩溃,尽管此时没有错误。

1个回答

14

首先,您需要检查系统中有多少GPU可用。这可以通过使用cudaGetDeviceCount来实现。

int deviceCount = 0;
cudaGetDeviceCount(&deviceCount);

然后检查用户输入是否大于可用设备数量。

if (userDeviceInput < deviceCount)
{
  cudaSetDevice(userDeviceInput);
}
else
{
  printf("error: invalid device choosen\n");
}

需要提醒的是,cudaSetDevice函数是以0为起始索引的!因此我会检查userDeviceInput < deviceCount


是的,这是一个不错的避免方法。但我想知道为什么它不起作用。 - Stefan
4
展示一个完整的示例会有帮助。你的错误检查可能使用了cudaPeekAtLastError(),它 不会 清除错误代码。每次你要求它返回最后一个错误(比如,在你的内核启动后)。相反地,cudaGetLastError()将清除它返回的错误(即,如果没有新的错误发生,未来的检查将不再返回那个错误,而是返回cudaSuccess)。这与API返回的错误代码不同。如果你想让内核启动不失败,在非法的cudaSetDevice(1)调用之后的某个地方做 cudaGetLastError 即可。 - Robert Crovella
我应该说:“如果你想让内核启动不表现为失败…” - Robert Crovella
@Robert,你能把这个发表为答案吗?这样我就可以接受了。因为你显然是正确的 :) 非常感谢! - Stefan
我实际上只是检查了从cudaSetDevice返回的值,该值包含错误但不会将其从cudaGetLastError的错误堆栈中删除。 - Stefan
1
我相信Hub的回答再加上我的评论会是一个不错的回应。如果你喜欢,可以接受它。仅凭我的评论,没有你详细展示错误检查类型的实际操作,可能不太有意义。我们已经看到,我的评论是错误的,因为你没有使用cudaPeekAtLastError。你的问题中缺乏明确的示例,这使得任何人都很难回答。 - Robert Crovella

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