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

标签 multithreading cuda unified-memory

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

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

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

最佳答案

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

但是,请记住 concurrentManagedAccess device property 时施加的限制。是真实的。在这种情况下,当您有托管缓冲区并启动内核时,不允许对该缓冲区或任何其他托管缓冲区进行任何类型的 CPU/主机线程访问, until you perform内核调用后的 cudaDeviceSynchronize()

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

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

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

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

关于multithreading - CUDA统一内存可以被另一个CPU线程写入吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54594686/

相关文章:

java - 在局部变量上同步

cuda - 当 block 的数量少于可用的 SM 时,如何将它们调度到 CUDA 中的 SM 中?

CUDA扭曲同步问题

cuda - 我们可以将 "normal"GPU 内存复制到 "unified"内存吗?

apache-spark - Spark执行内存监控

C - pthread_join() 挂起(有时)

java - 如何在其中一个工作完成后停止工作线程?

c++ - javacpp 中的 "a namespace name is not allowed"错误

cuda - 创建统一内存时是否需要提供 Gpu 上下文?

java - Java 中同步块(synchronized block)/方法中处理异常的最佳实践