CUDA 内核中映射的固定主机内存上的原子操作:做还是不做?

Far*_*zad 3 cuda atomic pci-e

CUDA 编程指南中指出,映射固定主机内存上的原子操作“从主机或其他设备的角度来看不是原子的”。我从这句话中得到的是,如果主机内存区域仅由一个 GPU 访问,则可以在映射的固定主机内存上执行原子操作(即使来自多个并发内核)。

另一方面,在尼古拉斯·威尔特( Nicholas Wilt)的《CUDA 手册》一书中,第 128 页指出:

不要尝试在映射的固定主机内存上使用原子,无论是主机(锁定比较交换)还是设备(atomicAdd())。在 CPU 方面,PCI express 总线上的外围设备看不到为锁定操作强制互斥的设施。相反,在 GPU 方面,原子操作仅适用于本地设备内存位置,因为它们是使用 GPU 的本地内存控制器实现的。

在映射的固定主机内存上从 CUDA 内核内部执行原子操作是否安全?我们可以依靠PCI-e总线来保持原子读-修改-写的原子性吗?

Arc*_*are 5

该警告适用于使用映射固定内存来协调 CPU 和 GPU 之间或多个 GPU 之间的执行的人。当我写这篇文章时,我没想到有人会在单 GPU 的情况下使用这种机制,因为 CUDA 提供了许多其他更好的方法来协调 CPU 和单个 GPU 之间的执行。

如果 CPU 和 GPU 之间存在严格的生产者/消费者关系(即生产者正在更新内存位置而消费者正在被动读取它),则可以预期在某些情况下可以正常工作。

如果 GPU 是生产者,CPU 会看到内存位置的更新,因为它们从 GPU 的 L2 缓存中发布。但是 GPU 代码可能必须执行内存屏障来强制发生这种情况;并且即使该代码在 x86 上工作,它也可能在没有英勇措施的情况下在 ARM 上崩溃,因为 ARM 不会监听总线流量。

如果 CPU 是生产者,则 GPU 将不得不绕过 L2 缓存,因为它与 CPU 内存不一致。

如果 CPU 和 GPU 尝试同时更新相同的内存位置,则没有机制可以确保两者之间的原子性。执行 CPU 原子将确保更新相对于 CPU 代码是原子的,执行 GPU 原子将确保更新相对于执行更新的 GPU 是原子的。

上述所有讨论都假设只有一个 GPU;如果涉及多个 GPU,则所有赌注都将取消。尽管 PCI Express 3.0 总线规范中提供了原子,但我认为 NVIDIA GPU 不支持它们。而且底层平台的支持也无法保证。

在我看来,无论开发人员试图通过对映射的固定内存执行原子操作来完成什么,都可能有一种更快、更有可能工作的方法,或者两者兼而有之。