关于可计算、图灵机及CPU性能

引言

在上篇博文 从超时处理说起,我们可以谈些什么 中,看到了一点点系统层面的同步问题,同步问题引出了锁机制及并发等关键难点要点,但是在深入研究之前,我们不禁想问:

到底发生了什么,造成我们现在必须要面对一系列的加锁同步等复杂的东西?

现在,我们就从计算机的本质来看看,计算机体系结构是什么样子的?

无尽的“贪婪”

可计算问题的解决

计算机的发明,初衷是为了高效完成复杂的计算,复杂计算人工也可以完成,但是效率不高。

这些问题可以归类成 计算问题 ,指的是:是否存在一个算法,能够在任意输入的情况下解决这个问题。当然,有些问题是不存在这样的算法的,对于此类问题就不能利用计算机实现。

针对可计算问题,图灵提出的图灵机模拟出了一种模型来解决这类问题。 只要能够实现图灵机模型的全部功能,就可以解决任何可计算问题。这就相当于化学方程式,只要这几种元素混合就会产生对应的结果。

我们现在的CPU指令集和编程语言都是 图灵完备 的,也即实现了图灵机模型的全部功能。与此同时,基于冯诺依曼体系结构的计算机硬件本身支持这些指令集的处理。这样子,我们现实世界中的计算机就可以实际去解决 可计算 问题了。
注:后文有关于图灵机的介绍

更快、更多的计算

虽然能够解决问题了,但是我们还是想要更快的计算速度,以及在单位时间内能够更多的完成计算问题,基于这样的推动力,下一步发展,可以想到的方案是什么?(针对单台计算机来说)

  1. 提升CPU执行指令的速度。
  2. 增加CPU的数量。
  3. 保持CPU的运行,使其尽量一直在处理各种计算任务

那么,下面我们就来看下具体设计细节如何提升?

更快的CPU

晶体管 -> 门电路 -> 集成电路 -> CPU,那么想要CPU更快,首先可以想到的是增加晶体管的数量。数量的增加必然带来几个问题:

  • 功耗:晶体管工作时,电能会有一部分变成热能,从而累积热量。这样的话CPU本身的散热是个问题
  • 体积:物理晶体管的增加肯定会导致CPU体积的变大
  • 制作工艺的要求:体积不能太大的情况下,又想放置多个晶体管,那么肯定会对制作工艺的要求越来越高

那么,除此之外,可以考虑让CPU运行的更快,也就是CPU运行频率变高,对应晶体管就是开关频率加速,那么也会遇到功耗瓶颈。

由于CPU执行的每条指令都要通过一些阶段来实现,如典型的:取指 -> 译码 -> 执行,我们可以认为这些对应CPU内部的不同电路。非要等待一条指令完成后再执行一条指令的话,实在是浪费性能。那我们在CPU中的译码电路执行的时候,就去运行取指电路,这样子各电路的利用率变高,使得CPU在一定时间内可以完成的总共的指令数增加。

这就是流水线技术。万事都有利弊,流水线技术必然导致复杂度的极速上升,同时为了提升流水线本身的效率,又需要引入一些解决方案来设计。

下面,我们就针对上述提到的问题进行剖析。

抽象模型与实际

上文提到了,图灵机是一个模型,而冯诺伊曼计算机以其特殊的结构,构造出了一台这样子的现实版图灵机。我们再来从图灵机出发,看看最最本质的东西。

图灵机

关于图灵机的定义,以下引自维基百科:

图灵的基本思想是用机器来模拟人们用纸笔进行数学运算的过程,他把这样的过程看作下列两种简单的动作:

  • 在纸上写上或擦除某个符号;
  • 把注意力从纸的一个位置移动到另一个位置;

而在每个阶段,人要决定下一步的动作,依赖于(a)此人当前所关注的纸上某个位置的符号和(b)此人当前思维的状态。

为了模拟人的这种运算过程,图灵构造出一台假想的机器,该机器由以下几个部分组成:

  1. 一条无限长的纸带TAPE。纸带被划分为一个接一个的小格子,每个格子上包含一个来自有限字母表的符号,字母表中有一个特殊的符号{\displaystyle \square }[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VBsw72mw-1571321220516)(https://wikimedia.org/api/rest_v1/media/math/render/svg/455831d58fa08f311b934d324adcff89a868b4e4)]表示空白。纸带上的格子从左到右依次被编号为0, 1, 2, …,纸带的右端可以无限伸展。

  2. 一个读写头HEAD。该读写头可以在纸带上左右移动,它能读出当前所指的格子上的符号,并能改变当前格子上的符号。

  3. 一套控制规则

    TABLE

    。它根据当前机器所处的状态以及当前读写头所指的格子上的符号来确定读写头下一步的动作,并改变状态寄存器的值,令机器进入一个新的状态,按照以下顺序告知图灵机命令:

    • \1. 写入(替换)或擦除当前符号;
    • \2. 移动 HEAD, 'L’向左, 'R’向右或者’N’不移动;
    • \3. 保持当前状态或者转到另一状态
  4. 一个状态寄存器。它用来保存图灵机当前所处的状态。图灵机的所有可能状态的数目是有限的,并且有一个特殊的状态,称为停机状态。参见停机问题

注意这个机器的每一部分都是有限的,但它有一个潜在的无限长的纸带,因此这种机器只是一个理想的设备。图灵认为这样的一台机器就能模拟人类所能进行的任何计算过程。

这里的关键在于,其实我们目前认知的计算机最最最本质的能力是:如果把纸带看成存储器,那么就是修改存储器中数据的能力,只不过,他是按照一定的规则来修改这些数据的。

数学层面证明了图灵机可以解决一切可计算问题,至于怎么证明的,我们也没必要研究。只要相信在数学这个理论大厦的基础上,图灵利用其证明了。

但是,我们需要对引文中提到的 停机问题 进行一点说明。

停机问题

停机问题的描述,见 维基百科:

停机问题(英语:halting problem)是逻辑数学可计算性理论的一个问题。通俗地说,停机问题就是判断任意一个程序是否能在有限的时间之内结束运行的问题。该问题等价于如下的判定问题:是否存在一个程序P,对于任意输入的程序w,能够判断w会在有限时间内结束或者死循环。

为什么提到图灵机必然会看到停机问题呢,分析它的意义在哪里呢?

认识到计算机能力的边界:图灵机模型这么厉害,那么是不是可以用来计算一切问题?答案当然不是的,比如停机问题。

所以说,停机问题是让我们认识到边界。很多理论研究也是,有人说理论研究的目的在哪里?研究个半天又没有实际成果,做不出成品。那么,我想说:

理论研究的意义在一定情境下是用来指导我们,帮助我们认识到能力边界。比如一些物理研究,就能帮助我们认识到一些美好的设想只能在电影中存在。

图灵机与冯诺伊曼机

冯诺伊曼计算机的组成结构包含:运算器、存储器、运算器、输入设备和输出设备。存储器相当于图灵机中的纸带和状态寄存器,运算器相当于图灵机中的规则,读写头相当于控制器。当然这样只是简单的类比,我们的目的在于回归本质:

对于数据的处理

稍微引申一下就是,我们想更快更多的计算 – 也就是更快更多的处理数据,那么也就意味着存在数据被改乱的可能,这也就是同步加锁并发等等一系列的核心问题。

可能会有疑问说,为什么修改存储器的数据,就能实现比如打字、点亮屏幕等效果呢?

在《深入理解计算机系统》中有一段话说的很好,大意如下:

指令集是对处理器的抽象

程序员并不需要了解处理器,只要按照指令集就可以编写好可以运行的程序,这就是抽象的力量。

就如同别人叫你打开灯,实际上你并不关心是什么灯如何打开,你只要走过去按下墙壁上的开关,屋顶的灯就打开了。所以我们同样可以说,这个开关就是灯的抽象。你改变了开关的状态(或者说是数值),最终会影响到屋顶灯的效果。

所以,我们将计算的本质在于对数据的处理,数据处理好了,后续的一系列动作自然就产生了效果。

当然了,实际上是电路的构造导致的,感兴趣的可以看看《编码:隐匿在计算机背后的奥秘》,非常有意思的一本书

再谈冯诺伊曼计算机

目前的计算机,我们可以认为是由:CPU、存储器(包括内存、磁盘等)、输入输出设备组成的。

而CPU中,CPU的核心组成元素由三部分组成:

  • 运算单元
  • 控制单元
  • 存储单元

CPU即对应冯诺伊曼体系的运算器和控制器,内存和磁盘等一系列存储设备则对应存储器。

提到CPU,最重要的必然是CPU的性能,性能高还是性能低这种描述太过于抽象,我们需要将其量化。就好比 你好高 和 你比较高,我们无法感知,但是说 你身高178,我们就很清晰了。

CPU性能量化

取指令
翻译指令
执行

CPU的指令逻辑可以简单看成是上述操作的循环,也就是不断地执行一条条指令。那么CPU的性能就是执行指令的速度,也可以看作完成同样的程序需要的时间长短,即:

执行时间 = 指令数 * 指令处理时长

指令数指的是完成一个程序需要多少条指令,比如100条,这个好理解。但是指令处理时长又怎么算起呢?

要回答这个问题,需要来看下晶振这个物理器件。

心跳与晶振

我们可以把晶振当作某个电路的心跳,它周期性的产生波动。就好比一个人在喊121指挥大家干活一样,晶振产生的震荡指挥着处理器内部器件之间的协调工作。当然了,一般来说不会直接使用晶振的震荡,而是通过分频(121喊得慢一些)或者倍频(121喊得快一些)来指挥工作。我们把相关电路叫做时钟电路。

处理器为什么需要时钟电路呢?

晶体管–>逻辑门–>集成电路,晶体管的开关状态切换来实现上层的电路。那么越是用到的晶体管多的电路,一般来说,其从输入到最终的输出,所花费的时间越长(假设是串行的)。晶体管的开关切换不可能超过光速,最终可能还是需要几皮秒的。

所以说,CPU内部的各种电路单元,他们执行一个操作的耗时是不同的。就好比流水线上的工人,前一个装的很快,那么后面的都要崩盘。

这也是处理器需要时钟电路的原因。

我们把时钟电路的震荡周期,称作 时钟周期时间

指令处理时长量化

一条指令会消耗多个时钟周期时间,因为比如取指令的操作,假设涉及到两个电路的串行联动,即A的输出作为B的输入,那么取指令这个操作最起码要消耗2个以上的时钟周期才能完成。

又因为每条指令涉及到的实际电路单元可能不同,所以需要平均计算。所以,一条指令的执行时长,可以看作是:

指令处理时长 = 平均每条指令花费时钟周期数 * 时钟周期时间

专业上,把平均每条指令花费时钟周期数(clock cycles per instruction)叫做术语 CPI

性能量化最终公式

综上,CPU的性能量化公式可以表示为:

CPU完成一项程序任务的时间 = 该程序的指令数 * CPI * 时钟周期时间

后记

本来想写锁机制的,但是从前言开始就一直顺着思路一路思考到了这里。有一些表述可能不合适,还是要依据书里面的内容。本文行文仅是按照逻辑思考的过程来的,后续也按照如此行文来梳理。

性能公式拿到了,随后我们就来看看现代计算机是如何提升CPU性能的。

推荐与引申

推荐阅读:

  • 入门:编码-隐匿在计算机背后的奥秘
  • 提高:计算机组成与设计:软硬件接口
  • 提高:深入理解计算机系统

可以引出的点:

  • 计算理论
  • 图灵完备
  • 晶体管 --> 逻辑门 --> 集成电路,这一条路是如何构建的
发布了39 篇原创文章 · 获赞 74 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/zhou307/article/details/102616176