为什么需要对指令进行重排序?
其实说到底都是源于对性能的优化,CPU运行效率相比缓存、内存、硬盘I0之间效率有着指 数级的差别,CPU作为系统的宝贵资源,那么如何更好的优化和利用这个资源就能提升整个计 算机系统的性能。其实与其说是指令重排序还不如更通俗点理解为这是一种优化思想,因为这 种思想在生活中处处可见,就像平常咱们做菜,咱们会选择在炒第一个菜的同时就在洗第二个 菜了,而且先做哪个菜取决于那个菜熟得比较慢,咱们就会把这些菜放到最先开始煮,因为 它在煮的过程中咱还可以做其它事情,这就是一种时间上的优化,在计算机领域也是一样,它 也会根据指令的类别做一些优化,目的就是把CPU的资源利用起来,这样就能就能提升整个计 计算机的效率。
三种重排序场景
1,编译器重排序
针对程序代码语而言,编译器可以在不改变单线程程序语义的情况下,可以对代码语句顺序进 行调整重新排序。
2、 指令集并行的重排序
这个是针对于CPU指令级别来说的,处理器采用了指令集并行技术来讲多条指令重叠执行,如 果不存在数据依赖性,处理器可以改变主句对应的机器指令执行顺序。
3、内存重排序
因为CPU缓存使用缓冲区的方式(Store Buffere )进行延迟写入,这个过程会造成多个CPU 缓存可见性的问题,这种可见性的问题导致结果的对于指令的先后执行显示不一致,从表面结 果上来看好像指令的顺序被改变了,内存重排序其实是造成可见性问题的主要原因所在,其原理可在上一篇可中详细了解。
指令重排序的原则(as-if-serial语义)
编译器和处理指令也并非什么场景都会进行指令重排序的优化,而是会遵循一定的原则,只有 在它们认为重排序后不会对程序结果产生影响的时候才会进行重排序的优化,如果重排序会改 变程序的结果,那这样的性能优化显然是没有意义的。而遵守as-if-serial语义规则就是重 排序的一个原则,as-if-serial的意思是说,可以允许编译器和处理器进行重排序,但是有 一个条件,就是不管怎么重排序都不能改变单线程执行程序的结果。
单线程重排序
比如下面这段代码来说,语句2和语句1、3之间没有任何依赖关系,而语句1和语句3却有 着明确的依赖关系,遇到这样的语句(换成指令也一样)编译器就认为先执行语句2再执行语 句1、3对程序结果是没有任何影响的,所以可以对语句2进行重排序,反之编译器不会对语 句3重排序到语句1之前,因为语句3和语句1是有数据依赖关系的,如果对3进行重排序就 有可能影响到最终的程序运行结果,这也就是as-if-serial语义所表达的,只要程序结果不 会改变,那么就算我重排序了代码和指令,但从结果上来看我好像就是完全串行按顺序的把代 码从头执行到尾。
a=l; //1
b=2; //2
c=a+l; //3
编译器优化后可能执行顺序如下
b=2; //2
a=l; //1
c=a+l; //3
Was this helpful?
0 / 0