memory-barriers 相关问题

内存屏障是一种特殊的处理器指令,它对内存访问在多处理器或多核系统中的其他处理器/内核可见的顺序施加限制。



在Atomic Store之前进行重新排序的写入

我有以下情况:我想响应某些事件来启动一个长时间的运行异步线程,但是只想在面对多个事件的情况下一次启动一个线程。基本上,我有以下内容:

回答 1 投票 0


STD::atomic

std::atomic<int> unique_ids; void foo() { int i = unique_ids.fetch_add(1, std::memory_order_relaxed); std::cout<<i; } int main(int argc, char* argv[]) { std::vector<std::thread> threads; for (int i = 0; i < 9; ++i) { threads.emplace_back(foo); } for (int i = 0; i < 9; ++i) { threads[i].join(); } std::cout << std::endl; return 0; } 我的目标是使用原子来为并发计划生成独特的ID,但我不在乎这些订单。 < 对于上述代码,我的理解是,尽管不能保证其订单,但FOO中的输出值应该有所不同。 I测试了上述代码一百次,所有结果都是我所期望的。我是原子 /记忆顺序的初学者,谁能帮助我澄清自己的理解? 提前感谢。 Aimin P.S。我想指出的是,这个问题与一个C++,std :: atomic,什么是std :: memory_order和如何使用它们的问题不同有关原子和记忆顺序的解释的问题。 这是放松记忆订购的合法使用。您只需要对其他对同一原子的访问就可以是原子。每个原子操作都具有该特征,无论记忆排序如何,或者根本不是原子。 内存顺序的规范仅与此线程之前和/或之后完成此线程的其他读取/写入有关,然后通过其他线程读取该线程(又称线程的顺序,请参见副作用另一个线程至少两个访问)。 由于这里只涉及一个单个内存访问(尽管读取模式 - 访问),记忆顺序是无关紧要的,放松效果会很好。 但是,读取 - 修改工艺的操作是特别的。这些始终具有全球总顺序,独立于指定的内存顺序;这意味着每个线程都会以相同的顺序看到副作用(原子的值);即使他们只阅读值,也没有人会首先看到3,然后是2。

回答 1 投票 0

从多个批次写入相同颜色的附件

我正在一台带有集成显卡(只有一个 VkQueue)的笔记本电脑上开发一个 Vulkan 应用程序,启动时我需要运行一个非常昂贵的片段着色器,其输出稍后被读取为纹理。

回答 1 投票 0

gcc 是否将宽松的原子操作视为编译器栅栏?

我在GCC8.3,x86-64 linux上有以下代码: // 文件:inc.cc int inc_value(int* x) { (*x)++; //std::atomic ww; //ww.load(std::memory_order_relaxed); (*x)++; 返回*x; }

回答 1 投票 0

获取-释放语义是否可以跨线程传递?

我最近遇到了关于获取-释放语义的传递性的两种看似相反的解释。第 1 页上的“具有获取-释放排序的传递同步”部分...

回答 1 投票 0

出队项目存在,但 std::counting_semaphore::try_acquire() 在单消费者 MPSC 队列中失败

我有一个单消费者、多生产者无锁队列 (MPSCQueue) 与 std::counting_semaphore 相结合,以在新项目入队时通知消费者。消费者使用 dequeue() 来...

回答 1 投票 0

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

使用 seq_cst 内存顺序,以下代码永远不应该有 v1 == 0 和 v2 == 2 。但它仍然只是打印出我的 Apple M1 芯片上发生了重新排序。我真的不知道为什么。 #包括 使用 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; } 这些值可以通过线程之间程序操作顺序的简单交错来解释。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 重新排序。

回答 1 投票 0

Apple M1 芯片上的 C++ 内存顺序不起作用

使用 seq_cst 内存顺序,以下代码永远不应该有 v1 == 0 和 v2 == 2 。但它仍然只是打印出我的 Apple M1 芯片上发生了重新排序。我真的不知道为什么。 #包括 使用 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; } 这些值可以通过线程之间程序操作顺序的简单交错来解释。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 重新排序。

回答 1 投票 0

为什么不同的线程可以看到不同的内存操作顺序?

以下代码是《C++ Concurrency in Action》(第二版)一书中的示例。作者提到线程Ta和Tb可以观察不同的内存状态: Ta 观察到 x == true 且 y ==

回答 1 投票 0

是否需要在compare_exchange_strong()之前调用load()?

我正在学习C++内存序列,我在Unreal Engine5中找到了这段代码。我的问题是为什么不直接调用compare_exchange_strong()而不是先调用load()? FHttpRequest* GetFreeReque...

回答 1 投票 0

顺序一致性和获取/释放语义之间有什么区别? [重复]

据我所知,获取/释放语义充当顺序一致性和较弱内存模型允许的无条件内存重新排序自由之间的中间立场(或“放松”,如......

回答 2 投票 0

我们是否需要一次性自旋锁的内存获取屏障?

对于锁(自旋锁、互斥锁),我们通常需要在加锁时添加acquire fence以保证锁的功能。 但这对于一次性自旋锁来说是必要的吗?例如: 整数值=0; 在...

回答 1 投票 0

从内存加载指针时,我们需要内存获取屏障吗?

一般情况下,我们需要使用内存屏障(防止编译器或CPU重新排序内存访问)来保证多线程同步,例如: 整数x=0; 整数y=0; 无效线程1(无效) { ...

回答 1 投票 0

C++的happens-before关系和memory_order_consume

考虑以下使用 std::memory_order_consume 同步数据的示例: 结构X { 整数我; std::string s; }; std::atomic p; std::atomic a; 无效create_x...

回答 1 投票 0

为什么C#的Thread.MemoryBarrier()使用“lock or”而不是mfence?

我正在阅读一些旧的 MS 文档,理论与实践中的 C# 内存模型,第 2 部分,并且有兴趣阅读: 一种可能的修复方法是在 ThreadA 和 Thra 中插入内存屏障...

回答 1 投票 0

C++原子变量内存顺序问题无法重现

大家。我编写了一个演示来重现 cppreference 中引用的问题。 cpp参考演示 我发现一些文档和博客说这可能不会在 x86 芯片上重现,但在 ARM 芯片上,是...

回答 1 投票 0

关于 StoreLoad 内存屏障

我不懂StoreLoad。 store1 StoreLoad load2是否意味着CPU的store指令不能在StoreLoad之后重新排序并且load指令不能在StoreLoad之前重新排序? 如果...

回答 1 投票 0

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.