我正在编写一个程序,该程序从相机检索图像并使用CUDA处理它们。为了获得最佳性能,我将CUDA统一内存缓冲区传递给图像获取库,该库将在另一个线程中写入该缓冲区。
这会导致各种各样奇怪的结果,使程序无法在我无法访问的库代码中挂起。如果我使用普通的内存缓冲区,然后复制到CUDA,则此问题已解决。因此我开始怀疑是否可能不允许从另一个线程进行写操作,并且像我一样在Google上搜索时,找不到明确的答案。
那么是否允许从另一个CPU线程访问统一内存缓冲区?
答案 0 :(得分:5)
从多个线程写入统一内存缓冲区应该没有问题。
但是,请记住当concurrentManagedAccess
device property为不为true时施加的限制。在这种情况下,当您拥有托管缓冲区并启动内核时,不允许对该缓冲区或任何其他托管缓冲区until you perform和cudaDeviceSynchronize()
进行任何类型的CPU /主机线程访问在内核调用之后。
在多线程环境中,这可能需要花费一些明显的精力才能实施。
如果这也是您的发帖,我认为这类似于this recital。请注意,TX2应该将此属性设置为false。
请注意,可以通过谨慎使用streams来修改非并发情况下的一般规则。但是,这些限制仍然适用于附加到已在其中启动内核的流的缓冲区(或未明确附加到任何流的缓冲区):如果上述属性为false,则任何CPU线程都无法访问。
这种行为的动机大致如下。 CUDA运行时不知道托管缓冲区之间的关系,无论这些缓冲区是在哪里创建的。在一个线程中创建的缓冲区可以很容易地在其中带有带有嵌入式指针的对象,没有什么可以防止或限制这些指针指向另一个托管缓冲区中的数据的。甚至是后来创建的缓冲区。甚至在另一个线程中创建的缓冲区。安全的假设是任何链接都是可能的,因此,在没有任何其他协商的情况下,当启动内核时,CUDA运行时中的托管内存子系统必须将所有托管缓冲区移至GPU。这使得所有受管缓冲区无一例外地不可访问CPU线程(任何线程,任何位置)。在正常的程序流程中,访问将在cudaDeviceSynchronize()调用的下一次出现时恢复。一旦发出调用的CPU线程完成了调用并继续进行,托管缓冲区将再次对(所有)CPU线程可见。另一个内核启动(任何地方)都会重复该过程,并中断可访问性。重复一遍,这是在GPU上的concurrentManagedAccess
属性 not true时有效的机制,并且可以通过上述流附加机制在某种程度上修改此行为。