2017-04-22 44 views
3

为了让事情变得简单并且为了专注于我的问题的核心,让我们假设由指针变量ptr在本地寻址的内存位置在几个进程之间共享。我特别使用C/++中的MPI共享内存窗口来分配和共享内存。要具体,让我们说ptr引用一个浮点变量,所以在当地我们有特定共享内存写入操作(MPI)的同步

float* ptr; 

现在假设所有进程尝试写入相同的值const float f到PTR,即

*ptr = f; 

我的问题是:考虑到所有进程试图以相同的方式修改字节的事实,即该事件f对于每个进程具有相同的值,这个操作是否需要同步或者是否可以同时执行。因此,我的问题归结为:对于并行写入操作浮点变量,是否有竞争条件导致不一致的字节模式的可能性,虽然每个进程都尝试以相同的方式修改内存。即如果我确实知道每个进程都写入相同的数据,那么我可以省略同步吗?

回答

1

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

请注意同步对象解决的其他问题,如可见性和内存重新排序,写入共享内存的内容是不相关的。

目前,该标准没有定义进程的思想(仅限于线程),也没有提供任何方法轻松实现进程之间的同步。

您在共享内存中分配一个std::mutex,并将其用作同步原语,或者使用它作为同步原语,或者依赖于互斥,信号量或事件等win32进程间同步原语。或者,如果您只想同步基元,则可以在共享内存上分配一个std::atomic<T>,并将其用作同步原语。

+0

非常感谢您的回答。你能否更详细地说出你的意思是“在不同的流程中调整大小没有意义”?如果我在MPI中实现了正确的同步(这肯定我知道该怎么做),我甚至不会使用同步对象。所以我不明白“能见度,记忆重排”因素如何?我肯定不会使用任何C++标准库功能来解决这个问题。另请注意,冲突在访问数据的不同进程之间,而不是线程之间。 – sperber

+0

这是一个错字,它是“居住”。如果您的MPI提供同步,这是一个不同的问题,我根据您的示例进行了回答,例如,写入来自不同进程的裸指针 –

+0

因此,在使用多个进程写入相同数据的内存重新排序方面会出现什么问题,即组件级别会出现什么问题? – sperber

1

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

实际上,在您的计算机上,基本上可以按照您认为它应该工作的方式工作。实际上,在某些体系结构中,事情并不如预期的那样顺利:如果CPU无法读取/写入与共享值一样小的内存块,或共享值的存储跨越对齐边界,这样的写入实际上也可以涉及读取,而读取 - 修改 - 写入可以具有恢复或破坏对存储器的其他改变的效果。

得到你想要的东西,最简单的方法就是做写为“宽松”的原子操作:

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

这确保了写为“原子”在不造成一个数据的意义除了在*ptr = f可能存在潜在问题的架构之外,不会发生任何开销。

+0

优秀的答案,谢谢,这些都是我正在寻找/怀疑的细节和提示。 – sperber

+0

请注意,这是“memory_order_relaxed”实际上是个好主意的情况之一。一般来说,对共享内存的所有访问都应该使用同步原语来保护,或者使用更强的内存排序来完成。 – Sneftel