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

Multithreading CUDA统一内存可以被另一个CPU线程写入吗?,multithreading,cuda,unified-memory,Multithreading,Cuda,Unified Memory,我正在编写一个程序,从相机中检索图像,并用CUDA进行处理。为了获得最佳性能,我将CUDA统一内存缓冲区传递给图像采集库,该库将写入另一个线程中的缓冲区 这会导致各种奇怪的结果,在我无法访问的库代码中挂起程序。如果我使用普通内存缓冲区,然后复制到CUDA,问题就解决了。所以我开始怀疑从另一个帖子上写东西可能是不被允许的,尽管我在谷歌上搜索,我还是找不到一个明确的答案 那么,是否允许从另一个CPU线程访问统一内存缓冲区?从多个线程写入统一内存缓冲区应该没有问题 但是,请记住当concurrentM

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

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


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

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

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

在多线程环境中,这可能需要一些明确的努力来实施

我认为这与你的帖子类似。请注意,TX2应将此属性设置为false

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


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

是的,这是我的帖子。你难住我了!如果我错了,请纠正我
cudaDeviceSynchronize
仅在GPU写入缓冲区时才需要,对吗?在我的例子中,摄像头线程没有GPU代码,所以我猜这应该没问题。我不同意这种说法。此外,我认为你没有领会这个概念。内核启动会导致任何CPU线程都无法访问所有托管缓冲区。不管这些内核在做什么或不做什么,或者它们是如何启动的,或者它们是在什么线程中启动的(取决于我在回答中添加的修改,我想这不适用于这里)。一旦启动内核,这种情况就会持续,直到调用
cudaDeviceSynchronize()
为止。是的,你是对的。我很困惑!但是,我仍然在实际调用CUDA的线程中调用了
cudaDeviceSynchronize
。缓冲区管理器确保在CUDA处理相同的缓冲区时不会将其传递给摄影机线程。这对他们来说应该很好,对吗?一旦内核在任何地方启动,任何在任何地方创建的托管缓冲区都会受到此限制。在我看来,您应该调查我在回答中提到的流连接机制。这允许您将托管缓冲区与流相关联,从而根据内核是否在特定流中启动来控制这些缓冲区的迁移。因此,如果内核在另一个线程中运行,我不能使用任何线程中的托管缓冲区?