CUDA统一内存可以被另一个CPU线程写入吗?

Can CUDA unified memory be written to by another CPU thread?

我正在编写一个程序,从相机中检索图像并使用 CUDA 处理它们。为了获得最佳性能,我将 CUDA 统一内存缓冲区传递给图像采集库,该库在另一个线程中写入缓冲区。

这会导致各种奇怪的结果,在我无权访问的库代码中程序挂起。如果我使用普通内存缓冲区然后复制到 CUDA,问题就解决了。所以我开始怀疑从另一个线程写可能是不允许的,并且像我一样用谷歌搜索,我找不到明确的答案。

那么是否允许从另一个 CPU 线程访问统一内存缓冲区?

多线程写入统一内存缓冲区应该没有问题。

但是,请记住当 concurrentManagedAccess device property is not true. In that case, when you have a managed buffer, and you launch a kernel, no CPU/host thread access of any kind is allowed, to that buffer, or any other managed buffer, until you perform 一个 cudaDeviceSynchronize() 内核调用后施加的限制。

在多线程环境中,这可能需要一些明确的努力来强制执行。

我认为这与 this recital 类似,如果这也是您的帖子的话。请注意,TX2 应将此 属性 设置为 false。

请注意,可以通过谨慎使用 streams 来修改非并发情况下的一般规则。但是,这些限制仍然适用于附加到其中启动了内核的流的缓冲区(或未明确附加到任何流的缓冲区):当上面提到的 属性 为 false 时,任何 CPU 线程的访问都是不可能。

这种行为的动机大致如下。 CUDA 运行时不知道托管缓冲区之间的关系,无论这些缓冲区是在哪里创建的。在一个线程中创建的缓冲区可以很容易地在其中包含带有嵌入式指针的对象,并且没有什么可以阻止或限制这些指针指向另一个托管缓冲区中的数据。甚至是后来创建的缓冲区。甚至是在另一个线程中创建的缓冲区。安全的假设是任何链接都是可能的,因此,在没有任何其他协商的情况下,CUDA 运行时中的托管内存子系统必须将 all 托管缓冲区移动到 GPU,当内核是推出。这使得 all 托管缓冲区毫无例外地无法被 CPU 线程(任何线程,任何地方)访问。在正常的程序流程中,访问在下一次调用 cudaDeviceSynchronize() 时恢复。一旦发出调用的 CPU 线程完成调用并继续前进,托管缓冲区将再次对(所有)CPU 线程可见。另一个内核启动(任何地方)重复该过程,并中断可访问性。重复一下,这是当 GPU 上的 concurrentManagedAccess 属性 为 not true 时有效的机制,并且可以通过上述方法稍微修改此行为流附加机制。