| 选课类别:计划内与自由选修 | 教学类型:理论实验课 |
| 课程类别:本科计划内课程 | 开课单位:计算机科学与技术系 |
| 课程层次:专业基础 | 学分:4.0 |
本课程作为计算机科学技术专业的入门课程,采取自底向上的教学模式,跨系统地介绍计算机系统的核心概念和设计思想。从介绍计算机系统的底层基础知识开始,逐步上升到操作系统和高级语言程序的接口层,将软件和硬件联系起来,阐述从问题描述到算出结果的七个层次的转换过程:从问题到算法的转换、从算法到高级语言程序的转换、从高级语言程序到(用指令集结构描述的)机器语言程序的转换、从指令集结构到微结构的转换、从微结构到逻辑电路的转换、从逻辑电路到晶体管器件的转换。主要讲授内容包括:从MOS晶体管开始,依次介绍逻辑门、锁存器、各种逻辑结构的设计;然后围绕一个简单的计算机设计LC-3,依次介绍冯?诺伊曼计算机系统模型、指令系统设计、汇编语言程序设计和微结构设计,为初学者建立起对计算机系统的完整认识。在此基础上,介绍汇编语言程序设计、物理设备的输入和输出机制、操作系统的陷入机制和子程序调用和返回机制、以及栈和数据转换的原理和机制。
安虹老师的《计算机系统概论(H)》课旨在从底层构建一台小计算机(LC-3),涉及从门电路到汇编语言的多层次内容。课程前期与数字电路有一些重叠,但也提供了更广泛的计算机系统概念,虽然课程名为概论,却未能全面涵盖计算机系统各模块。课程强调level of abstraction,但实验中未能充分体现这一思想,尤其是汇编语言练习更显繁复。
安虹老师授课细致且从容,时常重复内容以确保学生理解。然而,一些同学反映课程节奏较慢,信息密度低。上课采用英文教材和课件,增强了学生的英语阅读能力。课程还包含多次讨论课,但组织较为松散,收获有限。
课程包括多次作业和实验,作业虽不计分但必须提交,实验部分尤其受到重视,占总评比重较大。实验涉及编写LC-3汇编程序,后期大实验(汇编器和模拟器)工作量大且位于考试周附近,耗时较多。实验报告的详细程度对分数有显著影响,报告要求英文撰写。
期中和期末考试为开卷,题量大且全英文,涵盖抽象思维考察。给分强调实验表现,期末考试结束后有调分,优秀率较高达50%以上。然而,部分年份曾出现临时调整给分策略的情况,引发部分学生不满。
课程的在线资源丰富,包含作业、实验及教材链接,但助教表现不一,回应速度和反馈较为缓慢。一些年级的助教在出题方面过于复杂,增加考试难度。
这门课受益于其对计算机系统的系统性介绍,但在课程安排和给分标准上有调整空间。大部分同学认为课程适合理解底层系统设计,是为后续学习打下基础的好课;然而对于非计科专业选修学生,可能体验不佳,需慎重考虑课程难度和时间投入。
长文预警。本文还在更新,欢迎大家持续关注。
文章论点:这门课没有在前几课说的那么重要,相反在当前CS培养方案下可有可无。理由如下:内容上,这门课只是中科大CS大二必修课中数字电路和计算机组成原理的精简版,没有覆盖计算机系统结构的全貌,删去后也不会影响任何课程的学习。思想上,没有训练到计算思维。课程主旨中的level of abstraction在实验中没有体现。课程教材作者在UTexas开的课是给EE系(在中科大可以对应为6系)学生上的,并不在UTexas CS系的培养方案中,而CS和EE在系统栈是不同的。
建设性意见:我们也没有能力去改变培养方案。我只能给一些自学CS上的建议吧。入门CS推荐Berkeley的CS61系列。CS61A和CS61B分别介绍了如何将问题进行程序抽象和数据抽象,CS61C介绍了机器提供了什么抽象。注意:课程实验才是精华,请务必要做!不过CS61系列有一个缺点就是实验间不成体系。因此刷了CS61后,强烈推荐Stanford的计算机网络CS144。这门课的实验通过搭建不同的模块实现TCP协议,每个模块给的Specification ,模块间的Abstraction以及一些Implementation的细节说明得非常详细,模块也给了足够的单元测试,可以真正感受到优秀的系统是怎么搭建起来的。至于这门课,目前也已经是CS必修课了,只能在个人层面上建议大一就选课,就当适应国际优秀课程思维的过渡课程。其他网友总结的推荐课程:
https://conanhujinming.github.io/comments-for-awesome-courses/index.html
利益相关:17级计算机系本科生,本门课在没有卷bonus的情况下拿了4.0。目前做计算机系统的研究。今天来给这门课和妮可本科CS培养泼一盆冷水。
之所以这门课给低分,不是因为老师和助教的教学态度,相反,老师和助教都很用心,尤其是小邓学长,为我们精心设计了实验;也不是因为授课质量的问题,相反,这门课是本科前3个学期唯一能在形式上和世界一流大学接轨的CS课程。原因在于不合理的培养方案和授课内容。在广度上,同样的课时授课内容只有其他高校类似课程的一半,且多局限于数字电路和计算机组成原理,从计算机系培养方案中删去后不影响其他专业课的学习。在深度上,所谓的计算思维,abstraction相关能力也没有得到深刻培养。这是我本科阶段中预期收获和实际收获落差最大的一门课。至少我没见过前几节课一直反复强调这门课有多么重要多么优秀的课程,否则我也不会给低分。
我们来看看这门课程的名字《计算机系统概论》,有人就觉得这门课是计算机系统的导论课,为后续学习做铺垫的。可是这门课完全没有起到概论的作用。计算机系统不仅包括体系结构,还包括操作系统、编程语言、计算机网络、数据库系统、分布式系统和计算机安全等。当然,数据库系统、分布式系统更偏应用,很多原理性的思想来自于操作系统、编程语言和计算机网络,计算机安全也需要就具体的系统分析。因此《计算机系统概论》应该要覆盖体系结构、操作系统、编程语言和计算机网络的基本思想。可就实际的授课内容,正如 @nofear 和 @liuly 同学所言,计算机组成原理和数字电路中的内容完全可以覆盖这门课绝大多数内容。除此之外,@topusername 和 @SproutH 同学提到,这门课放在大二秋季学期学习,与数字电路同步,地位比较尴尬,降低了课程意义。我也赞同 @OREO 同学的观点,这门课可以帮助外系的同学了解计算机的最简单的硬件组成,但是给CS科班学生实在不是非常的有用,反而会占用大量时间。在17级及以前的培养方案中,模拟与数字电路、计算机组成原理、微机原理与系统B、计算机体系结构。这些课程完全能让大家学会如何造计算机from scratch。再加上这门课,体系结构学分比重实在过大,对比其他计算机领域课程学分和可怜的编程实践,显然是不平衡的。
那好,既然计算机组成原理和数字电路中的内容完全可以覆盖这门课,那么能从这上面能提炼出更深刻的思想和见解,那这门课也是有价值的。很可惜,绪论中在组成原理提过的von Neumann架构等都在组成原理里介绍。当然,这门课也有一个贯穿始终的思想level of abstraction。安虹老师也对那张从物理到应用的level of abstraction那张图说,这门课上完后什么都可以忘,除了这张图。正如李博杰学长 @boj 总结的一样,这门课介绍了从门电路到处理器,硬件给我们提供了怎样的接口和抽象。但是这门课给了我们这样的训练了吗?恐怕是没有。实验都是用汇编语言甚至是机器码写程序,优化指令执行时间和指令条数来进行记分搞军备竞赛。写满屏的jump和r1,r2命名的寄存器来写复杂的应用程序训练abstraction思维?这无非是更折磨人版本的程序设计罢了,很难从中学会减低真正系统的复杂性的方法。
这一点上看,数字电路和组成原理的Verilog实验才是训练abstraction思维的担当。前面一个实验用门电路搭造简单的可以被复用的mux等电路,经过了简单的测试证明在所有情况下都可用。等到要写register file和ALU等复杂模块,发现有些需要的功能和mux类似,我们完全可以放心地调用mux模块搭造。而时序逻辑比较复杂,状态机只写状态转移函数,其他数据千万不要在状态机模块里写,需要从状态推导出的数据调用状态机即可。这样只写简单部件,通过模块之间的组合构成复杂系统,这样的利用abstraction的Verilog代码绝对是最不容易出问题的。而不利用abstraction的Verilog代码出现bug很可能需要调半天(尤其是喜欢复制粘贴代码然后稍作修改的同学,很容易就忘记修改某一个地方)。这训练效果不就上来了吗。反观这门课,为了优化代码,我们不得不放弃一些便于我们思考的特性,如函数调用,甚至染上复制粘贴的坏习惯。大家可以看看CP-Miner这篇论文,有多少bug因为随意的复制粘贴代码而导致的。或许这门课实验的目的是为了体会逆abstraction思维的坏处,比如为什么不要用goto语句,细品图灵奖得主Dijkstra的Go-To Statement Considered Harmful吧。笑。
另外,我听说之后可能会开一门《计算系统概论B》给全校通修,具体授课会和这门课有偏差,暂不做评论。如果说全校通修的《计算机程序设计》能让学生学会如何把重复机械的工作交给计算机自动化,那么《计算系统概论》也应该让非计算机系学生理解如何分解复杂的问题使其简单化。如果《计算系统概论》实验没有达到这个目标,那还是一门平庸的课。如果反而让简单问题变得十分繁琐,那么我相信非计算机系同学看待这门课,就像非实验物理专业同学看待《大学物理实验》一样。

当然,如果这门课的内容是整个计算机系统的基础,那么提前学也是很有价值的。但事实恰恰相反。正因为系统的abstraction,无论是我们在实现OS的文件系统还是编译器的类型系统,都没有必要去考虑取指译码的数据通路。如果简单的编程需要考虑这些,恰恰是系统设计的失败。在考虑系统layer的某个特定问题时,通常只需要考虑上一个layer和下一个layer提供的abstraction即可。这才是真正的level of abstraction。并不是说知道怎么造计算机就能帮助解决计算机科学的所有问题。恕我再引用Dijkstra的话。
Computer science is no more about computers than astronomy is about telescopes, biology is about microscopes or chemistry is about beakers and test tubes. Science is not about tools. It is about how we use them, and what we find out when we do.

这门课中还提到了计算思维,引用了图灵奖得主Patterson的发言:在异构时代的程序员必须对于算法和硬件模型融会贯通。计算思维其实是由Jeannette M. Wing在2006年提出的。其中最显眼的一句话是:
Thinking like a computer scientist means more than being able to program a computer. It requires thinking at multiple levels of abstraction.
我认为Patterson实际的意思是要理解硬件提供的abstraction。举一个简单的例子,通常分析算法复杂度时,我们可以认为访问一次数据消耗的时间是一样的。但如果数据在硬盘中,我们必须以块的粒度访问数据,而且磁盘访问通常是系统的瓶颈。因此我们有了external memory algorithms,用访问磁盘块的I/O次数来衡量算法复杂度。著名的B+Tree和LSM-Tree就是典型的例子。同样,针对cache,我们也有cache-oblivious algorithms。非易失内存Persistent Memory出现后,我们的系统需要对性能做modeling (如论文 An Empirical Guide to the Behavior and Use of Scalable Persistent Memory),重新设计存储数据结构来利用它的性能 (如论文 ListDB: Union of Write-Ahead Logs and Persistent SkipLists for Incremental Checkpointing on Persistent Memory )。这些都不需要我们理解硬件的原理,只需要我们了解硬件的abstraction就能指导我们。这就是计算思维的魅力所在。
那么好,现在的培养方案达到Patterson所想的让学生掌握软硬件协同原理了吗?我想并没有。学的硬件课多并不代表能达到掌握这个原理,如果在同一水平层次上学习,仍然是无法达到进阶水平的。就大二学的硬件课《模拟与数字电路》《模拟与数字电路实验》《ics》《计算机组成原理》上来看,这些课的观点依旧停留在如何用构造电路执行程序这个层次。大二计算机系学生一直不断在这一层次上重复训练,给学生实际的编写程序的洞察相比投入的时间而言实在有点少。事实上,这种训练也达不到Patterson所说的懂硬件的层次。因为这些电路只是模型,了解ALU的工作原理并没有告诉你如何在软件层面上加速程序执行,也没有告诉你如何在硬件层面提供虚拟化和安全性。事实上,学习《计算机体系结构》才是软硬件协同的开始。比如利用Memory-Level Parallelism提出新的字典树数据结构Cuckoo Trie以及利用SIMD加速数据库。这些工作都不需要考虑硬件的底层原理。只要掌握一定的基础概念,任何人都可以进行进阶的学习。
这对于所有知识的学习都是一样的,很可惜这种事情一直在不断重演。最典型的例子是中科大不少学生对《吉米多维奇》和《电磁学千题解》类似的追捧。在大学学习中按部就班地跟着培养大纲走是有毒的,很多情况下只有进阶学习才能发现哪些基础是最重要的。在教学上典型的例子是《线性代数》,训练计算各种奇怪矩阵行列式的小技巧反而会让人忽视理解线性空间这个重要概念,导致后续学习机器学习和量子力学等课程时吃力。除此之外,低效的重复训练所带来的反而是厌恶,比如《微机原理与系统B》这门硬件课改为选修后,22年的课已经因选课人数过少而停开了。

我们再来重新审视一下实验。有一次实验要求优化汇编代码行数,有一次实验要求优化执行指令数。在汇编语言上优化应用代码确实是一个很hacker的行为。但这是正统的计算机系统学习方法吗?我觉得并不是。图灵奖得主Alan Kay 在 Normal Consider Harmful 提到一个他非常重要的观点“A point of view worth more than 80 IQ points”。他举了三个例子,达芬奇有很高的IQ,在他的时代构想了很多发明,但缺少足够的知识,达芬奇却不能够实现自己的发明。福特出生在合适的年代,那个年代积累了足够知识,得以大规模制造出汽车改变了人们的交通方式。而牛顿的微积分方法给我们一个outlook,只需用几个简单的定律就能描述物理世界,好像多了一个大脑,使得我们能更快地去掌握知识。这让现在的普通人就可以造出牛顿时代之前的最聪明的人都不可想象的事。Alan Kay也继续提到(36:35)
I believe one of the biggest problems with computing is, in a sense, we have too many smart people. It attracts cleverness and you can do clever hacks but the clever hacks don’t scale well.
我不否认中科大里聪明人很多,这点实验的复杂度不在话下。但是现实系统的复杂度已经到了聪明人也承受不了的程度。分布式一致性协议Raft的作者提及Paxos时指出
We struggled with Paxos ourselves; we were not able to understand the complete protocol until after reading several simplified explanations and designing our own alternative protocol, a process that took almost a year.
也就是说,一个Stanford的博士生理解一个现有问题的解决方案都要花一年。请问我们能指望世界上有多少聪明人帮助我们解决这么多复杂的问题呢?那么我们的CS有outlook使得我们可以方便的进行开发吗?有的,那就是通过specification和abstraction。specification是为了帮助程序更容易理解而做的约定,我们在实现时只需保证程序在约定的状态下执行。abstraction可以帮助我们找到最通用的,specification最简单的系统行为,我们先实现这些通用的系统行为,在此基础上就可以构建出更容易理解的系统。有兴趣的同学可以看看2020年图灵奖得主Alfred Aho和Jeffrey Ullman的Turing Lecture:Abstractions, their algorithms, and their compilers。
举一个简单的例子。在学习数据结构中,我们发现很多系统都要求取出当前集合最小元素的操作。比如,构建Huffman树需要找到当前频率最小的两个node,再加入一个新node,node数量最多为511。使用Dijkstra算法计算最短路径时,需要取出当前权最小的node,再更新其邻居,node数量最多为|V|。我们可以根据这个特性构建一个指定初始容量的优先队列。提供update(node, weight)和poll()两种操作。函数update的specification是改变元素node的权值weight。函数poll的specification是删除优先队列表示的集合中权值最小的元素,并返回给应用程序。这样一来,我们就构建了一个通用问题的abstraction。它的好处有三点。首先,只要有类似的问题满足指定的specification,就可以使用实现这个specification的系统,降低了我们的工作量。第二,提供abstraction构造出简单的specification非常容易进行测试,检验它的正确性。第三,具体的实现和specification是解耦的,也就是说我们可以有多个系统满足这个specification,在其中挑选任一系统,对使用这个系统的程序都没有影响。比如,优先队列的实现可以用时间复杂度为O(n)的方法遍历查找权值最小的元素,也可以使用复杂度为O(logn)的最小堆。如果我们在实现Dijkstra算法时发现O(n)复杂度的实现对于规模很大的图比较慢时,可以直接替换成O(logn)的实现,不需要改变最短路径的程序。
诚然,体系结构系统中一些问题确实对上层有影响。比如引入乱序执行,会使得我们在多处理器编程中需要考虑memory ordering,会引发meltdown安全漏洞。可惜这个课不仅没有解释这些进阶的问题,连C语言一些fallacies and pitfalls也没能很好地解释。这是上完其他高校的计算机系统入门课都能理解的问题,如https://nju-projectn.github.io/ics-pa-gitbook/ics2021/why.html。我会在下一段说明。
当然,正如 @Dune 同学所言,其他国内外知名高校CS专业都有名为ics的课程。那就让我们看看其他高校都在学什么。大多数高校都采用CMU的CSAPP作为参考教材,而这门课的内容只涵盖了CSAPP中PART I: Program Structure and Execution中2~4章的简单内容和其他的零散的一部分内容。而据我所知,大多数高校如上海交大等都能把CSAPP的12章内容讲8章以上。其他没有以CSAPP为主线的ics课程也各有特色。而我们的课程内容只能覆盖伯克利入门课CS61C近30讲中的不到10讲。再来看看国内高校南京大学的ics。不仅广度更广,还真正阐明了抽象思维,通过reading the f**king source code的方式,让学生获得了处理大型项目的能力,这才是系统编程真正需要的能力。授课内容少导致比较明显的体现就是上课节奏太慢,如 @什么昵称 同学所说,一个指令能讲半个小时。
可能有些同学还有疑问,大名鼎鼎的Yale Patt教授在UTexas 就是这样上课的。这个评论是说他上课不好吗?并不是。细心的朋友可能从网站上发现Dijkstra和Patt都在UTexas任职。Patt开的课是 EE 306 - Introduction to Computing Systems,不在UTexas CS系学生的培养方案中,而是给学电子工程的同学开设的,告诉那些学电路的同学怎么搭建通用的计算机,并在其上运行程序。这门课对于EE系还是相当优秀的课程。
UTexas CS系培养方案:https://catalog.utexas.edu/general-information/coursesatoz/c-s/
UTexas EE系培养方案:https://catalog.utexas.edu/general-information/coursesatoz/e-e/
但是,电子工程和计算机科学要做的事情是不同的。举一个简单的例子,LC3指令集默认程序从0x3000开始执行,现实中的很多指令集都是这样处理的,EE系用电路把计算机搭到这个地步就足够了。但是对于CS,故事才刚刚开始。既然是通用计算机,那就应该可以执行不同的程序。那么从一个程序切换到另一个程序执行时,我们是否需要把物理内存中0x3000开始的程序全部清除掉换成新的程序?不需要,我们可以用虚拟内存,假设每个程序指令都从虚拟地址的0x3000开始,但不同程序的虚拟地址可以映射到不同的物理地址上。这是这门课没有覆盖的,但确实是计算机系统的核心内容之一。所以,这门课只能覆盖第一个图中从电路到ISA的层次,没有达到“需要一门贯通课程,帮助学生从底层物理到高层应用,整体上理解计算机系统”的目的。
这里对Patt教授和安虹教授没有贬义的意思。这门课在2011年出现在国内确实让人眼前一亮,哪怕是EE系的课也确实值得国内CS系同学学习,这比国内一堆只在堆砌概念的课程不知道高到哪去了。十年前,科研上,计算机系统界顶级会议NSDI、PLDI、OSDI等鲜有中国大陆学者的身影。教学上,蒋炎岩博士在2009年在南京大学上操作系统课时还在写8086汇编,大学四年里没有人教profiler,trace。在这种背景下,能写出合格的系统就不错了,更别提跟上国际潮流。但是十年过去了,国内计算机系统学界进步有目共睹。我认为这门课已经不能算合格的CS系计算机系统入门课了。这里的批判不应该仅限于这门课,而是整个培养方案。我们应该思考为什么有很多同学觉得这门课能收获很大。
对于大多数同学而言,这门课是第一个可以称得上和国际接轨的课程,而且也没有偷跑学组成原理,所以很多同学收获很多。我看有些学弟学妹还提到这门课接触了linux,git,make,收获比较大。但这实际上是大一就应该学会的编程的正确方式,即使不是一开始就接触,大一第二学期的程序设计进阶课也该接触了,没接触的原因是前面课程设计偷懒。所以,我给这门课打低分的原因不是因为这门课差到极致了,而是因为这门课有很多的进步空间。如果我当年ics上课内容直接搬到当前中科大CS课程体系中,学弟学妹们还觉得这门课收获在科大CS培养方案算比较高的,妮可本科CS培养就真的不仅落后于国际一流名校,还彻底落后于其他华五高校了。
临时改变给分标准我是没有想到的。
另外今年这几个助教就像鬼一样,在群里面从不发言,私信也不怎么回,特别是不公示作业和实验情况,让人死的不明不白的。
这门课其实算是有点用,不过实在是浪费时间。性价比不高,非英才班的同学建议别选,如果是想要开阔视野的话不妨选吴俊敏的计算机系统详解(大一下就可以选,不过难度较高,但作为公选课给分好且轻松)。个人认为这门课不好水学分,能学到的东西也不是很多。
如果不是必修为什么要选这门课呢?
本人成绩虽不顶尖,期中期末在班上也算偏前,但仍被实验(尤其是汇编器和模拟器两个实验)烦到了。问题列出如下:
安虹老师讲课中规中矩,前几周基本都在吹水,后面还算是正常讲课了,可以接受。
给分还行,优秀率76%