CUDA流是否与设备相关?如何获取流的设备?

5
我有一个CUDA流,别人交给了我 - 一个cudaStream_t值。 CUDA运行时API似乎没有说明如何获取与此流相关联的设备的索引。
我知道cudaStream_t只是指向驱动程序级别的流结构的指针,但我不确定是否要深入了解驱动程序。有没有一种惯用的方法来做到这一点?或者有什么好理由不想这样做?
另一个方面是,该问题是否真的涉及与CUDA驱动程序可以确定指向的结构的设备身份相关联的流。

我不是CUDA驱动程序专家,也没有多GPU编程的实际经验。但我期望每个CUDA流都特定于特定的CUDA上下文。我还期望每个GPU都有自己的CUDA上下文。这意味着CUDA流句柄在设备之间不是唯一的,只是针对每个给定设备唯一的。因此,您可能需要在应用程序中传递一对{设备号,流句柄}。 - njuffa
@njuffa:如果一个CUDA流是上下文特定的,而且上下文是设备特定的,这难道不意味着CUDA流句柄在跨设备时是唯一的吗?也许我没有理解你的意思... - einpoklum
在所有设备上拥有唯一的流句柄意味着流句柄具有全局“命名空间”。我认为这种情况并不存在。因此,如果假设有两个GPU,每个GPU都有自己的上下文。在每个上下文中创建的第一个流可能会获得句柄值1。如果有人将值为1的流句柄传递给您的代码,那么它属于哪个设备?我们无法确定。 - njuffa
@njuffa:cudaStream_t是指向结构体的指针,而不是整数句柄(例如CUDA设备标识符)。你怎么会认为这些是非唯一的句柄? - einpoklum
@RobertCrovella 好的。 - Jared Hoberock
@RobertCrovella:但是可能情况是,即使CUDA驱动程序也无法确定流关联的设备,并且与其他设备一起启动将不会优雅地失败。我的意思是,这听起来不太可能,但这确实是问题的关键,因为如果我们知道CUDA驱动程序可以查看哪里,我们就可以自己查看那里。 - einpoklum
2个回答

2

是的,流是特定于设备的。

在CUDA中,流是特定于上下文的,而上下文是特定于设备的。

现在,使用运行时API时,您不会“看到”上下文 - 每个设备只使用一个上下文。但是如果考虑驱动程序API - 您

CUresult cuStreamGetCtx ( CUstream hStream, CUcontext* pctx );

CUstreamcudaStream_t是同一件事情 - 一个指针。因此,您可以获取上下文。然后,您设置或推送该上下文为当前上下文(在其他地方阅读有关如何执行此操作的说明),最后,您使用:

CUresult cuCtxGetDevice ( CUdevice* device ) 

获取当前上下文的设备。
所以,有点麻烦,但完全可行。

我轻松确定流设备的方法

我解决此问题的方法是让(类似于C ++)流包装器类在成员变量中保留(上下文和)设备,这意味着您可以编写:

auto my_device = cuda::device::get(1);
auto my_stream = my_device.create_stream(); /* using some default param values here */
assert(my_stream.device() == my_device());

我们可以不必担心它(+ 它不会触发额外的API调用,因为在构建时,我们知道当前上下文是什么以及它的设备是什么)。

注意:以上代码片段适用于至少具有两个CUDA设备的系统,否则不存在索引为1的设备...


刚开始接触CUDA,哇,API的一些遗留问题真是让人头疼。你完全期望一个流能够告诉你它来自哪个设备,但实际上并没有这个功能。还有NppStreamContext,这是你必须在使用NPP的流时使用的,但需要手动初始化8个结构字段,包括设备。当我正在处理一个流时。感谢您开始并继续开发这个库,这正是我期望NVIDIA提供的 :-)。 - aggieNick02
哈哈,我不知道 - NPP 不流行吗?如果你想在 GPU 上进行常见操作(如向图像添加通道或调整图像大小),但还不熟悉编写自己的内核,你会使用什么工具呢?不幸的是,我不认识任何 nVidia 的人,但如果有机会的话,我仍然会支持他们。 - aggieNick02
@aggieNick02:啊,好的,你在处理图像方面有所作为。不用理会我的评论,我把NPP和其他东西搞混了。 - einpoklum

0
关于显式流,根据我所知,实现是由其决定的,没有API为用户提供此潜在查询功能;我不了解驱动程序在此方面可以为您提供的功能,但是您始终可以查询流。
通过使用cudaStreamQuery,您可以查询所选设备上的目标流,如果它返回cudaSuccesscudaErrorNotReady,则表示该流存在于该设备上,如果它返回cudaErrorInvalidResourceHandle,则表示不存在。

当使用设备n'查询流程时,我是否保证从设备n获取cudaErrorNotReady? - einpoklum
如果正在查询的流存在于所选设备上,则一定会返回cudaStreamQuery或cudaErrorNotReady之一。前者表示已完成所有与相关流相关联的操作,而后者表示尚未完成;无论哪种情况,两者都表示该流存在。如果在流上得到cudaErrorInvalidResourceHandle错误,则意味着该流根本不存在。 - Iman
但是流能在两个设备上“存在”吗?更具体地说,假设在内部,流值只是其设备流数组中的索引。因此,流0将始终存在于所有设备上。我是否会从所有GPU获得cudaSucces和该cudaStream_t? - einpoklum
关于我的最后一条评论,请回复... - einpoklum

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