c++ - B.Stroustrup 新书中的优化与多线程

标签 c++ multithreading optimization c++11

请引用B.Stroustrup的《TCPL》第4版41.2.2 Instruction Reordering部分,我抄录如下:

To gain performance, compilers, optimizers, and hardware reorder instructions. Consider:

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

For this piece of code there is no stated reason to assign to x before assigning to x_init. The optimizer (or the hardware instruction scheduler) may decide to speed up the program by executing x_init = true first. We probably meant for x_init to indicate whether x had been initialized by initializer() or not. However, we did not say that, so the hardware, the compiler, and the optimizer do not know that.

Add another thread to the program:

// 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;
    // ...
}

Now we have a problem: thread 2 may never wait and thus will assign an uninitialized x to y. Even if thread 1 did not set x_init and x in ‘‘the wrong order,’’ we still may have a problem. In thread 2, there are no assignments to x_init, so an optimizer may decide to lift the evaluation of !x_init out of the loop, so that thread 2 either never sleeps or sleeps forever.

  1. 标准是否允许在线程 1 中重新排序? (即将引用标准中的一些内容)为什么这会加快程序的速度?
  2. 两个答案都在 this discussion on SO 中似乎表明当代码中有全局变量时不会发生这种优化,如上面的x_init。
  3. 作者所说的“将 !x_init 的求值提升到循环之外”是什么意思?是这样的吗?

    if( !x_init ) while(true) this_thread::sleep_for(milliseconds{10});
    
    y = x;
    

最佳答案

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

物有所值,prior to C++11 ,该标准在其抽象机器模型中没有多线程的概念。东西是a bit nicer这些天。

关于c++ - B.Stroustrup 新书中的优化与多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21762693/

相关文章:

iphone - 如何找到操作的时间值(value)来优化新的算法设计?

c++ - 在 C++ 中将结构类型转换为整数,反之亦然

c++ - 如何在 Cython 中正确管理 C++ 对象的生命周期?

java - 从非 UI 线程调用 Snackbar.make() 是如何工作的?

android - 仅在长时间操作期间显示的进度条

python - 优化蛮力数字求解器python的建议

c++ - 使用 QAudioRecorder 时禁止创建 wav 文件

c++ - 在 C++ 中找出随机数生成器的种子

C++ OTL 看不到外部数据库更改

ruby - 如何让Ruby捕获线程中的语法错误