CPU指令集的概念和作用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CPU指令集的概念和作用?相关的知识,希望对你有一定的参考价值。

此处不进行正式而科学的描述,如果想了解关于“指令集”最专业权威的定义,你可以去百度百科中搜索了解。
这里简单地打个比方:缺乏某种指令集的CPU,进行相关运算会非常慢甚至无法进行。就好比一个不会乘法口诀的人,想计算“一斤大白菜3块钱,买8斤需要多少钱”这个算数问题,只能掰着手指用加法慢慢算,结果算了半分多钟才出结果。
而拥有了指令集的加持后,就好比掌握了乘法口诀,可以瞬间“三八二十四”给出计算结果。
参考技术A 所谓指令集,就是CPU中用来计算和控制计算机系统的一套指令的集合,而每一种新型的CPU在设计时就规定了一系列与其他硬件电路相配合的指令系统。而指令集的先进与否,也关系到CPU的性能发挥,它也是CPU性能体现的一个重要标志。
一、指令集就是CPU能认识的语言,指令集运行于一定的微架构之上,不同的微架构可以支持相同的指令集,比如Intel和AMD的CPU的微架构是不同的,但是同样支持X86指令集,这很容易理解,指令集只是一套指令集合,一套指令规范,具体的实现,仍然依赖于CPU的翻译和执行。就像,同样是一段C语言代码,我们可以用不同的编译器去编译得到不同的可执行文件,当然,自然而言,效率也可能不一样。
二、指令集的作用, 就是告诉程序员/编译器, 汇编一定要有格式. 支持什么指令, 指令带什么限制条件, 用什么操作数, 用什么地址, 都是指令集规范的内容, 要是写错了, 就无法翻译成机器码.
指令集规范汇编, 汇编可以翻译成机器码, 机器码告诉CPU每个周期去做什么. 因此, CPU指令集是描述CPU能实现什么功能的一个集合, 就是描述"CPU能使用哪些机器码"的集合"。
三、软件意义上, "指令集"实际上是一个规范, 规范汇编的文件格式。

CPU指令集是描述CPU能实现什么功能的一个集合, 就是描述"CPU能使用哪些机器码"的集合"。本回答被提问者和网友采纳

java中volatile关键字的作用

java中volatile关键字的作用

一.内存模型的相关概念

大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入。由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于CPU执行速度很快,而从内存读取数据和向内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存。

  也就是,当程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。举个简单的例子,比如下面的这段代码:

i = i + 1;

  当线程执行这个语句时,会先从主存当中读取i的值,然后复制一份到高速缓存当中,然后CPU执行指令对i进行加1操作,然后将数据写入高速缓存,最后将高速缓存中i最新的值刷新到主存当中。

  这个代码在单线程中运行是没有任何问题的,但是在多线程中运行就会有问题了。在多核CPU中,每条线程可能运行于不同的CPU中,因此每个线程运行时有自己的高速缓存(对单核CPU来说,其实也会出现这种问题,只不过是以线程调度的形式来分别执行的)。本文我们以多核CPU为例。

  比如同时有2个线程执行这段代码,假如初始时i的值为0,那么我们希望两个线程执行完之后i的值变为2。但是事实会是这样吗?

  可能存在下面一种情况:初始时,两个线程分别读取i的值存入各自所在的CPU的高速缓存当中,然后线程1进行加1操作,然后把i的最新值1写入到内存。此时线程2的高速缓存当中i的值还是0,进行加1操作之后,i的值为1,然后线程2把i的值写入内存。

  最终结果i的值是1,而不是2。这就是著名的缓存一致性问题。通常称这种被多个线程访问的变量为共享变量。

  也就是说,如果一个变量在多个CPU中都存在缓存(一般在多线程编程时才会出现),那么就可能存在缓存不一致的问题。

  为了解决缓存不一致性问题,通常来说有以下2种解决方法:

  1)通过在总线加LOCK#锁的方式

  2)通过缓存一致性协议

  这2种方式都是硬件层面上提供的方式。

  在早期的CPU当中,是通过在总线上加LOCK#锁的形式来解决缓存不一致的问题。因为CPU和其他部件进行通信都是通过总线来进行的,如果对总线加LOCK#锁的话,也就是说阻塞了其他CPU对其他部件访问(如内存),从而使得只能有一个CPU能使用这个变量的内存。比如上面例子中 如果一个线程在执行 i = i +1,如果在执行这段代码的过程中,在总线上发出了LCOK#锁的信号,那么只有等待这段代码完全执行完毕之后,其他CPU才能从变量i所在的内存读取变量,然后进行相应的操作。这样就解决了缓存不一致的问题。

  但是上面的方式会有一个问题,由于在锁住总线期间,其他CPU无法访问内存,导致效率低下。

  所以就出现了缓存一致性协议。最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。

二.并发编程中的三个概念

在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题。我们先看具体看一下这三个概念:

1.原子性

  原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。

  一个很经典的例子就是银行账户转账问题:

  比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。

  试想一下,如果这2个操作不具备原子性,会造成什么样的后果。假如从账户A减去1000元之后,操作突然中止。然后又从B取出了500元,取出500元之后,再执行 往账户B加上1000元 的操作。这样就会导致账户A虽然减去了1000元,但是账户B没有收到这个转过来的1000元。

  所以这2个操作必须要具备原子性才能保证不出现一些意外的问题。

  同样地反映到并发编程中会出现什么结果呢?

  举个最简单的例子,大家想一下假如为一个32位的变量赋值过程不具备原子性的话,会发生什么后果?

i = 9;

  假若一个线程执行到这个语句时,我暂且假设为一个32位的变量赋值包括两个过程:为低16位赋值,为高16位赋值。

  那么就可能发生一种情况:当将低16位数值写入之后,突然被中断,而此时又有一个线程去读取i的值,那么读取到的就是错误的数据。

2.可见性

  可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

  举个简单的例子,看下面这段代码:

[复制代码](javascript:void(0)

以上是关于CPU指令集的概念和作用?的主要内容,如果未能解决你的问题,请参考以下文章

CPU的指令集主要都有哪些

精简指令集和复杂指令集的区别

INTEL和AMD的CPU都有很多指令集,这个有啥用?对电脑的运行速度有影响吗?

SSE、SSE2、SSE3指令集的区别?

奔腾4的CPU扩展指令集是啥

如何分享安卓修改手机CPU指令集