- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在 Intel x86/x86_64 系统上有 3 种类型的内存屏障:lfence、sfence 和 mfence。关于它们的使用的问题。对于顺序语义 (SC),对所有需要 SC 语义的存储单元使用 MOV [addr], reg + MFENCE
就足够了。但是,您可以编写整体代码,反之亦然:MFENCE + MOV reg, [addr]
。显然感觉,如果存储到内存的数量通常少于从内存中加载的数量,那么使用写屏障的总成本就会更低。并且在此基础上,我们必须使用顺序存储到内存,进行了另一个优化 - [LOCK] XCHG,由于“MFENCE inside in XCHG”仅适用于内存中使用的缓存行,因此可能更便宜XCHG ( video where on 0:28:20 said that MFENCE more expensive that XCHG ).
http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
C/C++11 Operation x86 implementation
- Load Seq_Cst: MOV (from memory)
- Store Seq Cst: (LOCK) XCHG // alternative: MOV (into memory),MFENCE
注意:有一个 C/C++11 到 x86 的替代映射,它不是锁定(或屏蔽)Seq Cst 存储,而是锁定/屏蔽 Seq Cst 加载:
- Load Seq_Cst: LOCK XADD(0) // alternative: MFENCE,MOV (from memory)
- Store Seq Cst: MOV (into memory)
不同之处在于,ARM 和 Power 内存屏障仅与 LLC(末级缓存)交互,而 x86 与低级缓存 L1/L2 交互。在 x86/x86_64 中:
lfence
在 Core1 上:(CoreX-L1) -> (CoreX-L2) -> L3-> (Core1-L2) -> (Core1-L1)sfence
在 Core1 上:(Core1-L1) -> (Core1-L2) -> L3-> (CoreX-L2) -> (CoreX-L1)在 ARM 中:
ldr; dmb;
: L3-> (Core1-L2) -> (Core1-L1)dmb;海峡; dmb;
: (Core1-L1) -> (Core1-L2) -> L3由 GCC 4.8.2 编译的 C++11 代码 - x86_64 中的 GDB:
std::atomic<int> a;
int temp = 0;
a.store(temp, std::memory_order_seq_cst);
0x4613e8 <+0x0058> mov 0x38(%rsp),%eax
0x4613ec <+0x005c> mov %eax,0x20(%rsp)
0x4613f0 <+0x0060> mfence
但为什么在 x86/x86_64 上通过 MOV [addr], reg + MFENCE
使用顺序语义 (SC) 而不是 MOV [addr], reg + SFENCE
,为什么我们需要全围栏 MFENCE
而不是那里的 SFENCE
?
最佳答案
sfence
不会阻止 StoreLoad 重新排序。除非有任何 NT 商店在飞行中,否则它在架构上是一个空操作。商店在它们自己提交到 L1d 并变得全局可见之前已经等待旧商店提交,因为 x86 不允许 StoreStore 重新排序。 (除了NT存储/存储到WC内存)
对于 seq_cst,您需要一个完整的屏障来刷新存储缓冲区/确保所有旧存储在任何后续加载之前都是全局可见的。参见https://preshing.com/20120515/memory-reordering-caught-in-the-act/例如未能使用 mfence
在实践中会导致非顺序一致的行为,即内存重新排序。
如您所见,可以将 seq_cst 映射到 x86 asm,并在每个 seq_cst 加载而不是每个 seq_cst 存储/RMW 上使用完全屏障。在那种情况下,您不需要任何有关商店的屏障说明(因此它们具有发布语义),但您需要 mfence
在每个 atomic::load(seq_cst)
之前.
关于c++ - 为什么 x86/x86_64 上的顺序语义通过 MOV [addr], reg + MFENCE 而不是 + SFENCE 使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19001823/
我已经看过 this answer和 this answer ,但对于 mfence 的等价或不等价,两者似乎都没有明确和明确的说明。和 xchg在没有非时间指令的假设下。 英特尔 instructi
我有一套并测试基于 xchg 的程序集锁。我的问题是: 在使用xchg 指令时是否需要使用内存防护(mfence、sfence 或lfence)? 编辑: 64 位平台:使用 Intel nehale
unsigned int lo = 0; unsigned int hi = 0; __asm__ __volatile__ ( "mfence;rdtsc" : "=a"(lo), "=d"
正如我们从之前对 Does it make any sense instruction LFENCE in processors x86/x86_64? 的回答中了解到的那样我们不能使用 SFENCE
据我所知,mfence 是一个硬件内存屏障,而 asm volatile ("": : : "memory") 是一个编译器屏障。但是,可以使用 asm volatile ("": : : "memo
我正在检查编译器如何在 x86_64 上发出多核内存屏障指令。以下代码是我使用 gcc_x86_64_8.3 测试的代码。 std::atomic flag {false}; int any_valu
Peterson 的锁码取自 (german) wikipedia : # define FALSE 0 # define TRUE 1 # define N 2 int turn; int inte
为什么 GCC 和 Clang 会为此代码 (x86_64, -O3 -std=c++17) 生成如此不同的 asm? #include int global_var = 0; int foo_se
Intel 的系统编程指南,第 8.3 节,关于 MFENCE/SFENCE/LFENCE 的说明: “以下指令是内存排序指令,而不是序列化指令。它们会耗尽数据内存子系统。它们不会序列化指令执行流。”
我有一个大小为 64 字节的对象: typedef struct _object{ int value; char pad[60]; } object; 在主要我初始化对象数组: volati
好的,我一直在阅读 SO 关于 x86 CPU 栅栏的以下问题( LFENCE 、 SFENCE 和 MFENCE ): Does it make any sense instruction LFEN
论文 N4455 No Sane Compiler Would Optimize Atomics讨论编译器可以应用于原子的各种优化。栏目下Optimization Around Atomics ,对于
在 Intel x86/x86_64 系统上有 3 种类型的内存屏障:lfence、sfence 和 mfence。关于它们的使用的问题。对于顺序语义 (SC),对所有需要 SC 语义的存储单元使用
我是一名优秀的程序员,十分优秀!