假设我的代码如下所示:
cudaHostAlloc( (void**)&pagelocked_ptr, size, cudaHostAllocDefault )
#pragma omp parallel num_threads(num_streams)
{
...
cudaMemcpyAsync( pagelocked_ptr + offset_thisthread
, src
, count
, kind
, stream_thisthread );
...
}
请注意,我明确避免在此设置标记cudaHostAllocPortable
。每个线程都使用自己的流,并且(我相信)隐式选择默认的Cuda设备。
根据示例第11.4节的Cuda,
页面只能固定到单个CPU线程。也就是说,如果任何线程将它们分配为固定内存,它们将保持页面锁定,但它们只会出现页面锁定到分配它们的线程。
他们继续说设置cudaHostAllocPortable
可以解决这个问题并允许所有线程将分配识别为固定缓冲区。因此,除非我指定cudaMemcpyAsync
而不是cudaHostAllocPortable
,否则上面的cudaHostAllocDefault
调用将失败。
Cuda C指南似乎与此信息相冲突。我的假设是Cuda上下文跟踪主机内存的哪些区域是页面锁定的,并且可以在没有中间分段副本的情况下传输到设备。根据目前的Cuda C指南3.2.1和3.2.4.1
此设备的主要上下文...在应用程序的所有主机线程之间共享。
和
默认情况下,使用上述页锁定内存的好处只能与分配块时的当前设备一起使用(并且所有设备共享相同的统一地址空间,如果有的话......)
这似乎意味着分配的页面锁定性质是跨越不同线程的Cuda调用所知,因为它们都使用设备0,并且所有线程中对cudaMemcpyAsync()
的调用都将成功。换句话说,如果我正确解释,只有在尝试在Cuda上下文之间共享页面锁定内存时才需要设置cudaHostAllocPortable
(例如,当一个人在使用cudaSetDevice
的GPU之间切换,并且卸载时每个页面锁定分配的大块)。
Cuda by Example中的信息是否过时了? Talonmies对this question州的回复
在CUDA 4之前,上下文不是线程安全的,需要通过上下文迁移API进行显式迁移。
但我不确定这是如何影响来自不同线程的Cuda调用的页面锁定状态的可见性。
提前感谢您的帮助!
答案 0 :(得分:3)
对于在特定设备上使用相同上下文的所有线程,页面锁定状态应该是明显的。如果您正在使用运行时API(就像您在这里一样),那么每个进程通常每个设备只有一个上下文,因此该进程中的所有线程应该在特定设备上共享相同的上下文,并且具有相同的任何指针视图在那种情况下。
the CUDA documentation中描述了cudaHostAllocPortable
标志的一个功能:
此调用返回的内存将被所有CUDA上下文视为固定内存,而不仅仅是执行分配的内存。
这意味着在多上下文设置或多设备设置中(上下文对于特定设备是唯一的),有必要使用此标志在该过程可见的所有上下文中从该指针获取固定行为