【问题标题】:Synchronization of particular shared memory write operations (MPI)特定共享内存写入操作 (MPI) 的同步
【发布时间】:2023-04-06 11:37:01
【问题描述】:

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

float* ptr;

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

*ptr = f;

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

【问题讨论】:

    标签: c++ mpi shared-memory race-condition atomic


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 非常感谢您的回答。您能否更详细地说一下“在不同进程中调整大小没有意义”是什么意思?如果我在 MPI 中实现了正确的同步(我肯定知道该怎么做),我什至不会使用同步对象。所以我不明白“可见性,内存重新排序”是如何影响的?我肯定不会使用任何 C++ 标准库功能来解决问题。另请注意,冲突发生在访问数据的不同进程之间,而不是线程之间。
    • 这是一个错字,它是“reside”。如果您的 MPI 提供同步,这是一个不同的问题,我已根据您的示例回答,例如写入来自不同进程的裸指针
    • 那么在多个进程写入相同数据的内存重新排序方面,这里可能会出现什么问题,即在汇编级别会出现什么问题?
    • @sperber 简而言之,编译器和 CPU 不知道多个线程将要从变量中写入/读取,并且可以以错误的方式优化代码。例如,编译器可以将++*f; ++*f; 合并到*f += 2,从而破坏从f 读取的其他线程所依赖的任何逻辑。
    • @sperber 这同样危险,因为编译器可能认为您的程序是完全单线程的,并且可以忽略对ptr 的写入,或者不忽略写入 - 但永远不会真正采取看看ptr 有什么。如果你从来没有读过ptr,那为什么一开始就写在那里?
    【解决方案2】:

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

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

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

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

    这样可以确保写入是“原子的”,不会导致数据竞争,并且不会产生任何开销,除非在 *ptr = f 存在潜在问题的架构上。

    【讨论】:

    • 很好的答案,谢谢,这些正是我正在寻找/怀疑的细节和提示。
    • 请注意,memory_order_relaxed 实际上是一个好主意的极少数情况之一。一般来说,对共享内存的所有访问都应该使用同步原语进行保护,或者使用更强的内存排序来完成。
    猜你喜欢
    • 2019-10-22
    • 2012-05-24
    • 2010-11-28
    • 2012-12-31
    • 2014-10-26
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 2012-07-05
    相关资源
    最近更新 更多