B.Stroustrup新书中的优化和多线程

Wak*_*zil 7 c++ optimization multithreading c++11

请参阅B.Stroustrup41.2.2节"TCPL"第4版的指令重新排序,我将在下面转录:

获得性能,编译器,优化器和硬件重新排序指令.考虑:

// thread 1:
int x;
bool x_init;
void init()
{
    x = initialize(); // no use of x_init in initialize()
    x_init = true;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

对于这段代码,没有明确的理由在分配给x_init之前分配给x.优化器(或硬件指令调度程序)可以通过首先执行x_init = true来决定加速程序.我们可能意味着x_init指示x是否已由initializer()初始化.但是,我们没有这么说,所以硬件,编译器和优化器都不知道.

向程序添加另一个线程:

// thread 2:
extern int x;
extern bool x_init;
void f2()
{
    int y;
    while (!x_init) // if necessary, wait for initialization to complete
    this_thread::sleep_for(milliseconds{10});
    y = x;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

现在我们遇到了一个问题:线程2可能永远不会等待,因此会将未初始化的x分配给y.即使线程1未将x_init和x设置为"错误的顺序",我们仍然可能会遇到问题.在线程2中,没有对x_init的赋值,因此优化器可能决定将!x_init的求值提升到循环之外,以便线程2永远不会睡眠或永远睡眠.

  1. 标准是否允许在线程1中重新排序?(标准中的一些引用即将发布)为什么会加快程序的速度?
  2. 关于SO的讨论中的两个答案似乎都表明,当代码中存在全局变量时,不会发生这样的优化,如上面的x_init.
  3. 作者的意思是"将!x_init的评估解除出来"?这是这样的吗?

    if( !x_init ) while(true) this_thread::sleep_for(milliseconds{10});
    
    y = x;
    
    Run Code Online (Sandbox Code Playgroud)

Buk*_*kes 3

这与其说是 C++ 编译器/标准的问题,不如说是现代 CPU 的问题。看看这里。编译器不会在 x 和 x_init 的赋值之间发出内存屏障指令,除非您告诉它。

无论如何,在 C++11 之前,该标准的抽象机器模型中没有多线程的概念。这些天情况好一点了