• 从源代码到Runtime发生的重排序


     源代码和Runtime时执行的代码很可能不一样,这是因为编译器、处理器常常会为了追求性能对改变执行顺序。然而改变顺序执行很危险,很有可能使得运行结果和预想的不一样,特别是当重排序共享变量时。

     从源代码到Runtime需要经过三步的重排序:

    重排序过程

    编译器重排序

     为了提高性能,在不改变单线程的执行结果下,可以改变语句执行顺序。

     比如尽可能的减少寄存器的读写次数,充分利用局部性。像下面这段代码这样,交替的读x、y,会导致寄存器频繁的交替存储x和y,最糟的情况下寄存器要存储3次x和3次y。如果能让x的一系列操作一块做完,y的一块做完,理想情况下寄存器只需要存储1次x和1次y。

    //优化前
    int x = 1;
    int y = 2;
    int a1 = x * 1;
    int b1 = y * 1;
    int a2 = x * 2;
    int b2 = y * 2;
    int a3 = x * 3;
    int b3 = y * 3;
    
    //优化后
    int x = 1;
    int y = 2;
    int a1 = x * 1;
    int a2 = x * 2;
    int a3 = x * 3;
    int b1 = y * 1;
    int b2 = y * 2;
    int b3 = y * 3;
    

    指令重排序

     指令重排序是处理器层面做的优化。处理器在执行时往往会因为一些限制而等待,如访存的地址不在cache中发生miss,这时就需要到内存甚至外存去取,然而内存和外区的读取速度比CPU执行速度慢得多。

     早期处理器是顺序执行(in-order execution)的,在内存、外存读取数据这段时间,处理器就一直处于等待状态。现在处理器一般都是乱序执行(out-of-order execution),处理器会在等待数据的时候去执行其他已准备好的操作,不会让处理器一直等待。

     满足乱序执行的条件:

    1. 该缓存的操作数缓存好
    2. 有空闲的执行单元

     对于下面这段汇编代码,操作1如果发生cache miss,则需要等待读取内存外存。看看有没有能优先执行的指令,操作2依赖于操作1,不能被优先执行,操作3不依赖1和2,所以能优先执行操作3。
    所以实际执行顺序是3>1>2

    LDR R1, [R0];//操作1
    ADD R2, R1, R1;//操作2
    ADD R3, R4, R4;//操作3
    

    内存系统重排序

     由于处理器有读、写缓存区,写缓存区没有及时刷新到内存,造成其他处理器读到的值不是最新的,使得处理器执行的读写操作与内存上反应出的顺序不一致

     如下面这个例子,可能造成处理器A读到的b=0,处理器B读到的a=0。A1写a=1先写到处理器A的写缓存区中,此时内存中a=0。如果这时处理器B从内存中读a,读到的将是0。

     以处理器A来说,处理器A执行的顺序是A1>A2>A3,但是由于写缓存区没有及时刷新到内存,所以实际顺序为A2>A1>A3。

    初始化:
    a = 0;
    b = 0;
    
    处理器A执行
    a = 1; //A1
    read(b); //A2
    
    处理器B执行
    b = 2; //B1
    read(a); //B2
    

    处理器和内存的交互

    阻止重排序

     不论哪种重排序都可能造成共享变量中线程间不可见,这会改变程序运行结果。所以需要禁止对那些要求可见的共享变量重排序。

    • 阻止编译重排序:禁止编译器在某些时候重排序。
    • 阻止指令重排序和内存系统重排序:使用内存屏障或Lock前缀指令
  • 相关阅读:
    【转】QPainter中坐标系变换问题
    【转】Python3 (入门6) 库的打包与安装
    【转】Python3 操作符重载方法
    【转】Python3 日期时间 相关模块(time(时间) / datatime(日期时间) / calendar(日历))
    正则表达式过滤HTML、JS、CSS
    JavaScript的类型转换
    JavaScript的数据类型,值和变量
    JavaScript介绍
    Ant学习笔记
    GeoServer端口配置
  • 原文地址:https://www.cnblogs.com/wewill/p/8086375.html
Copyright © 2020-2023  润新知