特定共享内存写入操作 (MPI) 的同步

Synchronization of particular shared memory write operations (MPI)

为简单起见并专注于我的问题的核心,我们假设多个进程共享一个由指针变量 ptr 本地寻址的内存位置。我特别在 C/++ 中使用 MPI 共享内存 windows 来分配和共享内存。具体来说,假设 ptr 引用了一个浮点变量,所以在本地我们有

float* ptr;

现在假设所有进程都试图将相同的值const float f写入ptr,即

*ptr = f;

我的问题是:考虑到所有进程都试图以相同的方式修改字节,即考虑到 f 具有每个过程的值相同。因此,我的问题归结为:对于并发写入操作,例如浮点变量,是否存在竞争条件导致字节模式不一致的可能性,尽管每个进程都试图以相同的方式修改内存。 IE。如果我确定每个进程写入相同的数据,那么我可以省略同步吗?

是的,您必须同步共享内存。修改线程驻留在不同进程这一事实没有任何意义,它仍然是数据竞争(从不同线程写入共享内存)。

请注意,同步对象还解决了其他问题,例如可见性和内存重新排序,写入共享内存的内容无关紧要。

目前,该标准没有定义进程(只有线程)的概念,也没有提供任何在进程之间轻松同步的方法。

您在共享内存中分配一个 std::mutex 并将其用作同步原语,或者依赖 win32 进程间同步原语,如互斥锁、信号量或事件。

或者,如果您只想同步原语,您可以在共享内存上分配 std::atomic<T> 并将其用作同步原语。

在 C++ 中,如果多个进程在未正确使用同步原语或原子操作的情况下写入同一内​​存位置,则会发生未定义的行为。 (也就是可能能用,也可能不能用,电脑可能会着火。)

实际上,在您的计算机上,它基本上可以按照您认为的方式工作。实际上,在某些体系结构上事情并没有按照您预期的方式进行,这实际上是合理的:如果 CPU 不能 read/write 一个与您的共享值一样小的内存块,或者如果共享值跨越对齐边界,这样的写入实际上也可能涉及读取,并且读取-修改-写入可能具有恢复或破坏对内存的其他更改的效果。

获得所需内容的最简单方法就是将写入作为 "relaxed" 原子操作:

std::atomic_store_explicit(ptr, f, std::memory_order_relaxed);

这确保写入 "atomic" 不会导致数据竞争,并且不会产生任何开销,除非在 *ptr = f 可能存在问题的架构上。