gpt4 book ai didi

c++ - 什么是 __asm volatile ("pause"::: "memory");做?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:33:56 31 4
gpt4 key购买 nike

我正在查看具有以下代码结构的开源 C++ 项目:

while(true) {
// Do something work

if(some_condition_becomes_true)
break;

__asm volatile ("pause" ::: "memory");
}

最后一条语句是做什么的?我知道 __asm 意味着它是一个汇编指令,我发现一些关于 pause 指令的帖子说线程有效地暗示核心释放资源并给其他线程更多资源(在超线程的上下文中)。但是 :::memory 有什么作用呢?

最佳答案

它是 _mm_pause() 和一个编译内存屏障,包装在一个 GNU C Extended ASM 语句中。 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

asm("" ::: "memory") 防止编译时对其内存操作进行重新排序,例如 C++11 std::atomic_signal_fence(std::memory_order_seq_cst) 。 (不是 atomic_thread_fence ;尽管在 x86 上阻止编译时重新排序足以使其成为获取 + 释放栅栏,因为 x86 允许的唯一运行时重新排序是 StoreLoad。)请参阅 Jeff Preshing 的 Memory Ordering at Compile Time 文章。

使 asm 指令部分非空也意味着这些 asm 指令将在每次 C 逻辑上运行该源代码行时运行(因为它是 volatile )。

pause 防止推测负载导致内存排序错误推测管道清除(又名机器核弹)。它在等待查看内存中的值的自旋循环内很有用。

您可能会在没有使用 C++11 std::atomic 编写的自旋循环中发现此语句,告诉编译器它必须重新读取全局变量的值。 (因为 "memory" 破坏意味着编译器必须假定 asm 语句可能已经修改了任何全局可访问内存的值。)

这看起来像您找到它的上下文:some_condition_becomes_true 可能包括读取非 atomic/非 volatile 全局。

循环的 C++11 等价物:

#include <atomic>
#include <immintrin.h>
std::atomic<int> flag;

void wait_for_flag(void) {
while(flag.load(std::memory_order_seq_cst == 0) {
_mm_pause();
}
}

(不完全相同,因为你的版本有一个完整的编译器障碍,而我的只有一个 seq-cst 加载,所以它不是一个完整的信号栅栏。但是可能不需要的东西,他们只是使用了比必要的更强的东西来获得 volatile 的效果)。


如果没有屏障或使 flag 成为原子,编译器会将其优化为:

// Do something work

if(some_condition_becomes_true) {
// empty
} else {

while(true) {
// Do something work
__asm volatile ("pause" ::: ); // no memory clobber
}
}

它会将对 some_condition_becomes_true 的检查提升到循环之外,不会每次都重新读取全局。

关于c++ - 什么是 __asm volatile ("pause"::: "memory");做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50428450/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com