简体   繁体   English

memory barrier 和 complier-only fence 有什么区别

[英]What is the difference between memory barrier and complier-only fence

As the question stated, I'm confused about the difference between memory barrier and complier-only fence.正如问题所述,我对 memory 屏障和仅编译器屏障之间的区别感到困惑。

Are they the same?它们相同吗? If not what is the difference between them?如果不是,它们之间有什么区别?

As a concrete example, consider the following code:作为具体示例,请考虑以下代码:

int x = 0, y = 0;

void foo() {
    x = 10;
    y = 20;
}

As it stands, without any barriers or fences, the compiler may reorder the two stores and emit assembly (pseudo)code like就目前而言,没有任何障碍或栅栏,编译器可能会重新排序这两个商店并发出汇编(伪)代码,如

STORE [y], 20
STORE [x], 10

If you insert a compiler-only fence between x = 10;如果在x = 10; and y = 20; y = 20; , the compiler is inhibited from doing this, and must instead emit ,编译器被禁止这样做,而是必须发出

STORE [x], 10
STORE [y], 20

However, suppose we have another observer looking at the values of x and y in memory, such as a memory-mapped hardware device, or another thread that is going to do但是,假设我们有另一个观察者正在查看 memory 中xy的值,例如内存映射硬件设备,或者另一个线程将要执行的操作

void observe() {
    std::cout << x << ", ";
    std::cout << y << std::endl;
}

(Assume for simplicity that the loads from x and y in observe() do not get reordered in any way, and that loads and stores to int happen to be atomic on this system.) Depending on when its loads take place with respect to the stores in foo() , we can see that it could print out 0, 0 or 10, 0 or 10, 20 . (为简单起见,假设在observe()中来自xy的加载不会以任何方式重新排序,并且加载和存储到int恰好在这个系统上是原子的。)取决于它的加载何时发生存储在foo()中,我们可以看到它可以打印出0, 010, 010, 20 It might appear that 0, 20 would be impossible, but that is actually not so in general.看起来0, 20是不可能的,但实际上并非如此。

Even though the instructions in foo stored x and y in that order, on some architectures without strict store ordering , that does not guarantee that those stores will become visible to observe() in the same order.即使foo中的指令以该顺序存储xy ,但在某些没有严格存储顺序的架构上,这并不能保证这些存储将以相同的顺序对observe()可见 It could be that due to out-of-order execution , the core executing foo() actually executed the store to y before the store to x .可能是由于乱序执行,执行foo()的核心实际上在存储到y之前执行了对x的存储。 (Say, if the cache line containing y was already in L1 cache, but the cache line for x was not; the CPU might as well go ahead and do the store to y rather than stalling for possibly hundreds of cycles while the cache line for x is loaded.) Or, the stores could be held in a store buffer and possibly flushed out to L1 cache in the opposite order. (比如说,如果包含y的缓存行已经在 L1 缓存中,但x的缓存行不在;CPU 最好提前 go 并存储到y而不是在缓存行为x已加载。)或者,存储可以保存在存储缓冲区中,并可能以相反的顺序刷新到 L1 缓存。 Either way, it is possible that observe() prints out 0, 20 .无论哪种方式, observe()都可能打印出0, 20

To ensure the desired ordering, the CPU has to be told to do so, often by executing an explicit memory barrier instruction between the two stores.为了确保所需的顺序,必须告诉 CPU 这样做,通常是通过在两个存储之间执行显式memory 屏障指令。 This will cause the CPU to wait until the store to x has been made visible (by loading the cache line, draining the store buffer, etc) before making the store to y visible.这将导致 CPU 等到x的存储可见(通过加载缓存行、清空存储缓冲区等),然后再使y的存储可见。 So if you ask the compiler to put in a memory barrier, it will emit assembly like因此,如果您要求编译器放入 memory 屏障,它会发出类似这样的程序集

STORE [x], 10
BARRIER
STORE [y], 20

In this case, you can be assured that observe() will print either 0, 0 or 10, 0 or 10, 20 , but never 0, 20 .在这种情况下,您可以确信observe()将打印0, 010, 010, 20 ,但绝不会打印0, 20

(Please note that many simplifying assumptions have been made here. If trying to write this in actual C++, you'd need to use std::atomic types and some similar barrier in observe() to ensure its loads were not reordered.) (请注意这里做了很多简化的假设。如果试图在实际的 C++ 中写这个,你需要在observe()中使用std::atomic类型和一些类似的屏障来确保它的负载没有被重新排序。)

A memory barrier is implemented in hardware, and stops the CPU itself from reordering the instructions. memory 屏障在硬件中实现,并阻止 CPU 本身对指令重新排序。

However, a compiler-only fence stops the compiler's optimizer from reordering instructions, but the CPU can still reorder them.然而,仅编译器的栅栏会阻止编译器的优化器对指令重新排序,但 CPU 仍然可以对它们重新排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM