Apple M1 芯片上的 C++ 内存顺序不起作用:即使使用 seq_cst 也会发生重新排序?

问题描述 投票:0回答:1

使用 seq_cst 内存顺序,以下代码永远不应该有 v1 == 0 和 v2 == 2 。但它仍然只是在我的 Apple M1 芯片上打印

Reorder happened
。我真的不知道为什么。

#include <semaphore.h>
#include <cstdio>
#include <atomic>
#include <thread>

std::atomic<int> v1, v2;
sem_t start_1, start_2, complete;

int main() {
    sem_init(&start_1, 0, 0);
    sem_init(&start_2, 0, 0);
    sem_init(&complete, 0, 0);

    std::thread t1([&] {
        while (true) {
            sem_wait(&start_1);

            v1.store(1, std::memory_order_seq_cst);
            asm volatile("":: : "memory");
            v2.store(2, std::memory_order_seq_cst);

            sem_post(&complete);
        }
    });

    std::thread t2([&] {
        while (true) {
            sem_wait(&start_2);

            int val1 = v1.load(std::memory_order_seq_cst);
            asm volatile("":: : "memory");
            int val2 = v2.load(std::memory_order_seq_cst);

            if (val1 == 0 && val2 == 2) {
                puts("Reorder happened");
            }

            sem_post(&complete);
        }
    });

    for (int i = 0; i < 1000000; i++) {
        v1 = v2 = 0;
        sem_post(&start_1);
        sem_post(&start_2);

        sem_wait(&complete);
        sem_wait(&complete);
    }

    t1.detach();
    t2.detach();
    return 0;
}
c++ atomic apple-m1 arm64 memory-barriers
1个回答
0
投票

这些值可以通过线程之间程序操作顺序的简单交错来解释。

seq_cst

StoreStore 或 LoadLoad 的正确试金石需要以与存储相反的顺序加载,并在第 2 个加载结果中看到 
v1.load gets 0 both stores in order v2.load gets 2

,第一个加载结果中非零。


但即使使用 0

进行此测试,您也可能不会看到此类重新排序,因为两个变量可能最终位于同一缓存行中,因此 CPU 没有理由对它们重新排序。 特别是因为两个加载地址同时准备好。 请参阅

C++ 原子变量内存顺序问题无法重现 LoadStore 重新排序示例

,了解有关 C++ 和您所针对的 ISA 允许的内存重新排序效果的实际演示的一些建议。
相关的不完全重复:无法让 C++ 的 seq_cst 内存模型工作

- 构造不良的石蕊测试的另一种情况,其中所谓有趣的结果可能会发生在 relaxed 中。 那是为了 IRIW 重新排序。


© www.soinside.com 2019 - 2024. All rights reserved.