2

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

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

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

4

1 回答 1

5

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

但是,请记住当concurrentManagedAccess 设备属性不正确时施加的限制。在这种情况下,当您拥有托管缓冲区并启动内核时,不允许任何类型的 CPU/主机线程访问该缓冲区或任何其他托管缓冲区,直到您执行cudaDeviceSynchronize()内核调用之后。

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

如果这也是您的帖子,我认为这与此独奏会相似。请注意,TX2 应将此属性设置为 false。

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

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

于 2019-02-08T15:22:30.840 回答