对优化说不 - Linux中的Barrier

1、CPU乱序执行

参考:https://blog.csdn.net/u013836909/article/details/120917553

1-1、前言

乱序优化包括:

  • CPU乱序执行优化
  • 编译器乱序优化

对应的限制乱序优化的方式:

  • 内存屏障
  • 优化屏障

1-2、CPU乱序执行

CPU在保证结果一致的情况下,把原来有序的指令列表,按照指令依赖关系和指令执行周期,重新安排执行顺序。

CPU乱序优化在一定程度上可以提高程序的运行速度。在多核情况下,由于CPU内部的高速缓存, 乱序执行对访问指令的影响可能导致对数据的影响不能及时的反映到主存上,从而导致结果错误。

主存储器(Main memory),简称主存。是计算机硬件的一个重要部件,其作用是存放指令和数据,并能由中央处理器(CPU)直接随机存取。现代计算机是为了提高性能,又能兼顾合理的造价,往往采用多级存储体系。即由存储容量小,存取速度高的高速缓冲存储器,存储容量和存取速度适中的主存储器是必不可少的。主存储器是按地址存放信息的,存取速度一般与地址无关。32位(比特)的地址最大能表达4GB的存储器地址。这对多数应用已经足够,但对于某些特大运算量的应用和特大型数据库已显得不够,从而对64位结构提出需求。

CPU乱序的本质原因是CPU为了效率,将长费时的操作“异步”执行,排在后面的指令不等前面的指 令执行完毕就开始执行后面的指令。而且允许排在前面的长费时指令后于排在后面的指令执行完。

1-3、内存屏障

大多数现代计算机为了提高性能而采取乱序执行,这使得内存屏障成为必须。

内存屏障,也称内存栅栏,内存栅障,屏障指令等, 是一类同步屏障指令,是CPU或编译器在对 内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点 之后的操作。

语义上,内存屏障之前的所有写操作都要写入内存;内存屏障之后的读操作都可以获得同步屏障之 前的写操作的结果。因此,对于敏感的程序块,写操作之后、读操作之前可以插入内存屏障。

大多数处理器提供了内存屏障指令:

完全内存屏障(full memory barrier):保障了早于屏障的内存读写操作的结果提交到内存 之后,再执行晚于屏障的读写操作。 内存读屏障(read memory barrier):仅确保了内存读操作。 内存写屏障(write memory barrier):仅保证了内存写操作。 X86指令集中的内存屏障指令是: sfence:写屏障store fence,串行化发生在SFENCE指令之前的写操作但是不影响读操作, 即在sfence指令前的写操作当必须在sfence指令后的写操作前完成。 lfence:读屏障load fence,串行化发生在SFENCE指令之前的读操作但是不影响写操作,即 在lfence指令前的读操作当必须在lfence指令后的读操作前完成。 mfence:读写屏障,串行化发生在MFENCE指令之前的读写操作,即在mfence指令前的读 写操作当必须在mfence指令后的读写操作前完成。 ARM指令集中的内存屏障指令(隔离指令):

dmb:数据存储器隔离,数据内存屏障指令,Data Memory Barrier。DMB指令保证: 仅当 所有在它前面的存储器访问操作都执行完毕后,才提交(commit)在它后面的存储器访问操 作。其它数据处理指令等可以越过 DMB 屏障乱序执行。 dsb:数据同步隔离,数据同步屏障指令,Data Synchronization Barrier。比DMB严格: 仅 当所有在它前面的存储器访问操作都执行完毕后,才执行在它后面的指令(亦即任何指令都 要等待存储器访问操作——译者注) isb:指令同步隔离,指令同步屏障指令,Instruction Synchronization Barrier。最严格:它 会清洗流水线,以保证所有它前面的指令都执行完毕之后,才执行它后面的指令。即ISB 屏 障之前的指令保证执行完,屏障之后的指令直接flush掉再重新从Memroy中取指。 存储器也提供了另一套语义的内存屏障指令:

acquire semantics: 该操作结果可利用要早于代码中后续的所有操作的结果。 release semantics: 该操作结果可利用要晚于代码中之前的所有操作的结果。 fence semantics: acquire与release两种语义的共同有效。即该操作结果可利用要晚于代码 中之前的所有操作的结果,且该操作结果可利用要早于代码中后续的所有操作的结果。

https://www.scss.tcd.ie/Jeremy.Jones/VivioJS/caches/MESIHelp.htm https://www.cnblogs.com/straybirds/p/8856726.html

2、简介

suppress:镇压;(武力)平定;压制;禁止(发表);查禁;封锁;抑制;控制;忍住

我们编写的源代码需要经过编译器转换成机器指令,最后由CPU执行这些指令。编译器作为一个“翻译官”,并不会老老实实地逐条翻译,而是会对我们的代码按照自己的“想法”进行调整和重组。CPU作为一个执行部件,对交给它的指令也不会规规矩矩的逐条执行,而是会重新排序之后执行。

这么“不尊重”我们的代码顺序,它们有权利这么做吗?它们有,因为它们高举的是“为效率优化”的大旗,一切都是为了你编写的代码能更快地执行,就像小时候某些家长常说的“都是为了你好”。

为了我好我就一定能好么,那可不一定,因为他们虽然经验丰富,但毕竟没有我自己对自己的了解那么深。编译器和CPU固然厉害,但它们都有个局限:无法理解代码执行的上下文联系。它们都只能假定一段代码是在单线程的环境下运行,因此它们做出的优化在面对多核多线程的环境时,就可能是不妥当的。最懂代码本身逻辑的,还是编写这段程序的人。

然而不可否认的是,编译器和CPU所做出的优化确实对性能提升明显,我们不可能完全弃之不用,所以需要在必要的时候suppress一下这些优化。

https://zhuanlan.zhihu.com/p/96001570

感觉就算深入也没有太大的意义,感觉后面也会忘记,算了,有机会再深入研究吧。

results matching ""

    No results matching ""