(2) 单核读取
执行流程是:
(资料图片仅供参考)
CPU A发出了一条指令,从主内存中读取x。
(3) 双核读取
执行流程是:
CPU A发出了一条指令,从主内存中读取x。
CPU A从主内存通过bus读取到 cache a 中并将该 Cache line 设置为E状态。
CPU B发出了一条指令,从主内存中读取x。
(4) 修改数据
执行流程是:
CPU A 计算完成后发指令需要修改x.
CPU A 将x设置为M状态(修改)并通知缓存了x的 CPU B, CPU B 将本地 cache b 中的x设置为I状态(无效)
(5) 同步数据
那么执行流程是:
CPU B 发出了要读取x的指令。
CPU B 通知CPU A,CPU A将修改后的数据同步到主内存时cache a 修改为E(独享)
CPU A同步CPU B的x,将cache a和同步后cache b中的x设置为S状态(共享)。
3、CPU存储模型简介
当多个CPU同时访问缓存中的共享数据时,为了保证数据的一致性,引入了MESI协议。这个协议定义了缓存行的四种状态,用来表示数据在不同CPU的缓存中的状态。当一个CPU对缓存进行读取或写入操作时,可能会导致缓存中的数据状态变得不一致。为了解决这个问题,缓存控制器需要监听本地和远程操作,并对相关的缓存行状态进行相应的修改,以保证数据在多个缓存之间的一致性。
然而,保证缓存一致性需要进行消息传递,而这个过程需要时间。状态的切换会引入更多的延迟,并且某些状态的切换需要特殊的处理,可能会阻塞处理器的执行。这些问题会给系统的稳定性和性能带来一些挑战。
为了解决这些问题,引入了存储缓存(Store Buffer)和无效队列(Invalidate Queue)。存储缓存是一种特殊的缓存区域,用于暂时存储将要写入缓存的数据。当CPU执行写操作时,它将数据先存储到存储缓存中,而不是直接写入缓存。这样做的好处是,CPU可以继续执行后续的指令,而无需等待写操作完成。存储缓存会在合适的时机将数据写入缓存,并确保数据的一致性。
无效队列是用于处理无效状态的缓存行的队列。当一个CPU将缓存行标记为无效时,它将该信息添加到无效队列中。其他CPU可以检查无效队列,获取关于缓存行状态的更新信息,并进行相应的处理。
通过引入存储缓存和无效队列,可以避免处理器因为等待远程缓存状态的确认而被阻塞,从而减少时间的浪费。这样处理器可以继续执行其他指令,提高了性能。
(1) 存储缓存
在没有存储缓存的情况下,当CPU要写入一个数值时,可能会面临以下情况:
如果这个数值不在CPU的缓存中,那么CPU需要发送一个信号给其他部件,告诉它们需要读取和失效(无效化)这个数值的状态。然后CPU需要等待这个信号的响应,然后才能将这个数值写入到缓存中。
如果这个数值在CPU的缓存中,并且它的状态是独占(Exclusive)的,那么CPU可以直接修改这个数值。
如果这个数值在CPU的缓存中,但它的状态是共享(Shared)的,那么CPU需要发送一个使其他CPU感知到这个更改的信号,然后等待其他CPU的响应,然后才能进行修改。
在这些情况下,很可能会涉及到CPU与其他CPU进行通信,并且需要等待它们的回复。这会浪费很多时钟周期。为了提高效率,可以采用异步的方式进行处理:首先将要写入的数值存储到一个缓冲区(Buffer)中,然后发送通信信号,等待信号被响应后,再将数值应用到缓存中。并且,这个缓冲区还可以让CPU读取数值。这个缓冲区就是存储缓冲区(Store Buffer)。而不需要等待对某个数值的写入指令完成才继续执行下一条指令,CPU可以直接从存储缓冲区中读取这个数值的值。这种优化称为存储转发(Store Forwarding)。
简而言之,存储缓存的作用是提高CPU写入数据时的效率。它通过使用存储缓冲区来暂时存储待写入的数据,异步地进行通信和操作,以减少CPU与其他部件之间的等待时间,从而提高计算机的整体性能。
(2) 无效队列
在多个CPU之间进行数据同步时,一个CPU可能会发送一个"Invalidate"(使无效)的信号给其他CPU,以通知它们某个特定的数据已经发生了变化。然而,如果接收到"Invalidate"信号的CPU立即采取行动去与其他CPU同步数据,那么这个过程可能会导致相当长的时钟周期延迟。
为了解决这个问题,接收到"Invalidate"信号的CPU并不会立即采取行动,而是将这个"Invalidate"信号放入一个叫做"Invalidate Queue"(使无效队列)的队列中,并立即发送响应信号。等到适当的时机,CPU再去处理这个"Invalidate Queue"中的"Invalidate"信号,并进行相应的处理操作。
换个方式理解,我们可以把这个过程类比成一个小区内的信箱系统。当有人给你寄来一封信件("Invalidate"信号),你并不会立即停下手头的工作去处理它。相反,你会将信件放入你的个人信箱("Invalidate Queue"),并立即回复发送方说你已经收到了。然后,当你有空闲时间时,你会去检查你的信箱,并处理里面的信件。
通过使用"Invalidate Queue",CPU可以更加高效地处理接收到的"Invalidate"信号,而不会立即中断当前的工作。这样,CPU可以根据自己的时间表进行合理的调度,以最大程度地提高处理效率。
总之,通过使用"Invalidate Queue",接收到"Invalidate"信号的CPU可以在合适的时机进行数据同步处理,而不会立即中断当前工作。这种优化方法可以减少时钟周期延迟,提高CPU的整体性能。
四、乱序执行
计算机内部有一个很重要的部分叫做CPU(中央处理器),它是负责执行计算和指令的核心。有一种特性叫做乱序执行,它可以让CPU更加高效地工作。乱序执行意味着CPU不必按照指令在程序中的顺序依次执行,而是根据情况自动地重新安排指令的执行顺序。
想象一下,您是一名厨师,面前有一张食谱,上面列着各种不同的烹饪步骤。通常情况下,您可能会按照食谱上的顺序,依次完成每个步骤。但是,有时候某些步骤可能会占用很长时间,例如等待水煮沸或者烤箱预热。如果您按照食谱的顺序等待每个步骤完成,可能会导致整个烹饪过程变得非常慢。
这时,您可能会聪明地采用乱序执行的方式。也就是说,您可以在等待某个步骤完成的同时,开始做其他不依赖于该步骤的工作。例如,您可以准备其他需要切割的食材,或者开始准备下一道菜的材料。这样,您能够更加高效地利用时间,使整个烹饪过程更快完成。
同样地,CPU的乱序执行也是为了更高效地利用时间。当CPU执行一条指令时,有时会遇到需要等待某些数据准备就绪的情况。如果按照指令在程序中的顺序等待每个数据就绪,CPU的工作效率可能会降低。乱序执行允许CPU在等待某些数据就绪的同时,开始执行其他不依赖于这些数据的指令。这样,CPU就能更加充分地利用时间,提高整体的计算速度。
乱序执行需要CPU内部的一些智能调度和判断机制来决定指令的执行顺序。这些机制能够分析指令之间的依赖关系,判断哪些指令可以并行执行,以及在等待某些数据就绪时可以执行哪些其他指令。通过乱序执行,CPU能够更好地利用计算资源,提高计算机的性能。
总而言之,乱序执行是CPU的一种智能特性,它使得CPU可以不按照指令在程序中的顺序依次执行,而是根据情况自动重新安排指令的执行顺序。这样可以更高效地利用时间,提高计算机的运行速度。就像厨师在烹饪过程中聪明地安排工作顺序一样,乱序执行让CPU更加聪明地处理指令,使计算机工作更快更高效。
CPU 执行乱序主要有以下几种:
写写乱序(store store):a=1;b=2; -> b=2;a=1;
写读乱序(store load):a=1;load(b); -> load(b);a=1;
读读乱序(load load):load(a);load(b); -> load(b);load(a);
读写乱序(load store):load(a);b=2; -> b=2;load(a);
总而言之,CPU的乱序执行优化指的是处理器为提高运算速度而做出违背代码原有顺序的优化。