计算机科学与技术本科知识体系
前两天给小学妹阐述了一下本校计算机科学与技术专业本科生需要掌握的知识体系。自觉比较有道理,整理一下发上来。适合的阅读对象:刚进入计算机系,对整个计算机科学技术的知识体系尚未了解的同学。本校学生获益尤大。
整个计算机科学就像人一样,有两条腿。一条叫做数学(基础),一条叫做物理(基础)。数学主要指的是数理逻辑。其中比较重要的是形式逻辑系统、Turing论题和Churcher论题。形式逻辑系统用逻辑的方法描述这个世界,在寥寥数条公理和推理规则之上构筑了整个逻辑系统、数论系统乃至计算机科学。Turing论题是计算机科学的基础,它点出了形式逻辑系统的威力:只要是人能计算的,机器都能用形式逻辑的规则进行计算。并且它提出了一种实现的方法,就是Turing机。Churcher论题指出了形式逻辑系统的不足:人能证明的,机器不一定能证明。更准确的说是,在形式逻辑系统中,不存在一种通用的算法,能判断所有命题的真假。这就是计算机科学的数学基础。
而计算机技术的物理基础就是数字逻辑电路。这里不说模拟电路啊电磁学啊,因为感觉和“逻辑”联系不是很大。首先数字电路中给出了逻辑的电路实现,比如如何实现这样的电路——仅当两输入均为高电平时输出为高电平——即与门。然后数字电路给出了组合逻辑的设计方法。这直接使算术逻辑单元(ALU)的设计成为可能。最后,数字电路给出了时序逻辑的设计方法,典型的结果就是寄存器、计数器的出现,使得时序控制成为可能。
但仅仅是数学和物理远不足以构成计算机科学与技术这样庞大复杂的知识体系。从历史的角度来看,对计算能力的渴求直接造就了计算机的出现。什么是计算机?高效完成计算的机器。为了实现用机器来高效计算这个目标,我们至少需要解决两个问题:首先,如何和机器沟通,亦即如何让它明白自己应当做什么,这就是软件知识系统的起源。然后,机器自身如何运作,这就是硬件知识系统的起源。再后来,随着时代的进一步发展,又诞生了很多对计算能力也有需求的新的科学分支,于是如何应用计算机的科学也就应运而生了。下面将从硬件、软件、应用这三个层次,自底向上分析计算机科学技术的知识架构。
数字电路已经实现了ALU、寄存器(存储器)等等基本部件。下一个问题就是如何用这些部件构成一个能完成高效计算的机器。现代常用计算机的体系结构是由冯.诺依曼同学指定的,称为冯.诺依曼结构。这位同学把整个计算机拆成了5大块:运算器、控制器、存储器、输出设备和输出设备。计算机采用2进制。指令和数据以同等的地位存放在存储器里。计算机进行计算时,控制器负责全局的调度,先去存储器拿指令,然后根据指令的内容(比如要求计算a + b)去存储器取操作数(比如取回a和b)。随后将操作数(a和b)和操作类别(加法)送给运算器,运算器算啊算啊,算好了再根据控制器的指示把结果(a + b的和)送回存储器。这就是计算机中最简单的工作流程。关于计算机究竟是怎么干活的,在计算机组成原理这门课中进行介绍。这门课程不仅介绍了整个计算机系统的组成,而且分别详细介绍了各个部件的工作原理,比如总线、存储器等等。最后,还会涉及到CPU的设计等问题。
在科大,硬件实验也是硬件学习不可或缺的组成部分。数字电路实验主要给同学们一个实践基本的电路设计方法的机会。现代的电路设计不像以前画电路图,然后手工蚀刻那样麻烦,而是采用硬件描述语言(HDL)的方式。在电脑上敲敲代码,告诉电脑你想设计一个什么样的电路,电脑就会自动进行综合、布线,最终将结果烧到FPGA或者CPLD这样的芯片里就可以直接用了。数字电路实验就是让同学们体验一下这样的过程,了解HDL和FPGA的基本使用方法。至于计算机组成原理实验,主要是让同学们利用HDL设计计算机的各个部分,如寄存器堆、时序控制部件、SRAM、程序计数器等等。最后设计一个简单的8指令CPU。至于更复杂CPU——比如16指令、32指令乃至兼容8086指令集的CPU——的设计,留到CPU设计与测试这门课中讲解。
有了计算机组成原理的基础,计算机就可以造出来了。更高一层的课程是将原理拓展到实践——微机原理。这门课程以现代常用的x86架构为例,介绍8086处理器典型的指令,让人和电脑的交互在现实中成为可能。在这门课里,将会教授如何通过机器语言和汇编语言和电脑进行最底层的沟通,让电脑按照人的指令进行计算。可以说,到了这门科学发展起来的时候,计算机已经进入实用的阶段了。
一门科学不涉及定量的数学计算,自称“科学”时总是没有什么底气。本科阶段接触的硬件方面的顶级课程——计算机体系结构——就给了硬件科学这样的底气。这门课从数学的角度介绍了定量评估计算机性能的方法,并且从不同的角度给出了优化计算机性的手段:指令集的合理设计、流水线技术、高速缓存的合理设置等等。至此,本科阶段学习的硬件课程告一段落。
下面介绍软件方面的知识。这一部分对于非计算机科学与技术专业,比如计算机应用、计算机工程甚至非计算机专业的同学来说就相对熟悉了。在介绍整个知识体系之前,我们先来看一下典型的软件开发的流程:
拿到一个软件开发任务——往小了说比如就是平时上课的一个project,第一步就是需求分析:分析这个程序的输入是什么、输出是什么,输出和输入之间满足怎样的数学关系。在确定了需求以后,需要进行的就是算法分析:分析这个问题如何进行求解。根据典型的算法设计思想,结合既有的常用算法确定适用于这个问题的算法——是用最土的深搜,广搜,还是动态规划、贪心,或者更高级的A*搜索、子句归结等等。确定了算法之后,就需要根据设定的算法来确定算法实现的基础——数据结构。比如算法只要求对相邻元素的访问但是插入删除操作频繁,采用链表就好;要求对线性元素的随机访问,就需要顺序表或者哈希表等等。在确定了数据结构以后,不要忘了对整个软件的架构进行验证:根据算法划分的模块是否足够合理,它们能否正常配合工作?因为整个程序的架构一旦到了实际编码阶段很难再更改,所以在编码前应当专门留心思考。接下来的工作就简单了:实际编码、调试、测试等等。当然,以上的各步之间顺序是可以更改的,比如Thinking in C++就建议在设计程序前先编写测试代码,而软件工程则要求在整个开发过程中维护开发文档等等。
从软件开发的任务出发,就可以很容易的领会到软件科学的体系架构了。首先,我们需要有一种高级语言来与电脑进行符合人类思维的交流。在它的基础上,就可以实现数据结构,从而为算法的实现打好基础。数据结构之上自然是算法。再往上是一些架构性的程序设计思想和规范,比如面向对象的思想、软件工程的思想等等。软件科学到此似乎就比较完善了。但是不要忘了高级语言下面还有支撑它的基础:编译器和操作系统。这两门课:编译原理和操作系统就成为了沟通软件和硬件之间的桥梁。
至于计算机应用,涉及到的领域就太多了。举例来说,人工智能、数字信号处理、计算机网络、操作系统等等等等。这里将操作系统也列为计算机的应用,是因为它的实现也用到了很多计算机科学的知识,比如算法、图论等等,也是需要下层知识的支撑的。每一门领域中,又各自有它自己的数学作为基础:比如人工智能需要形式逻辑,数字信号处理需要信息论、积分变换和采样理论,计算机网络对概率论的应用较多等等。因此,计算机应用可以分为两层,下层是数学,上层则是各个具体的学科。
到这里,整个计算机科学技术的知识系统基本上阐述完了。用图来表示的话大概是下面这个样子:
再观察可以发现,在整个体系中,数学贯穿了始终。可以说,数学是计算机科学技术的灵魂,扎实的数学基础对于这个专业的学生来说是相当大的优势。