写在最前的一些吐槽¶
众所周知,马克思主义最重要的一句话是"理论指导实践,实践检验理论"。
但是有些人显然认为数学分析、高等代数、TCS是人类智慧的结晶;而真正落到实处的工具(例如git等)是应用层的东西,是"俗物"。在许多大学的基础教育中都出现了这样的弊病,即过于注重理论而忽视实践。最终培养出来的不少学生,化身"数学*的搬运工",在集群里拉屎。
所谓"数学的搬运工",指的自然不是真正的数学研究者们;数学自然也不是数学。这种人有一个通病:特别喜欢理论,但是在其他方面(尤其是工程、生活、常识认知方面)上很差。其实差也不是问题,很多著名的理论研究者都有这样那样的奇怪行为习惯或者生活习惯。
但是这种人最大的问题是,明知自己将要从事工程实践,却不去主动提升自己在该方面的能力;更要命的是,这种人还喜欢把自己的世界观强加给别人,觉得只要理论水平高就行了,实践能力不重要了。
每个人脑子里实际上都隐含着一个World Model,在执行某个行为之前,大概率会在脑子里模拟一下动作的可能结果,俗称"过脑子"。而数学*的搬运工显然就是那些理论很好,但是过脑子能力很差的人。对于他们来说,过脑子这个动作是非常困难的,因为他们的World Model里缺乏一些基本的常识和经验,这些常识和经验是通过实践积累起来的,而不是通过理论学习来的。
但更恶心的是,数学*的搬运工还会自我繁殖。一旦这些搬运工们在大学里占据了主导地位,他们就会把自己的世界观强加给学生们,于是出很多过分看重理论水平的题,让学生们觉得只要理论水平高就行了,实践能力不重要了。进而实现了他们的排外和自我繁殖,培养出更多的搬运工来。在项目上,上述情况就会导致OIer的通病:小细节上造火箭,大瓶颈却搁着不动;码风问题甚至相对而言已经变成一个小问题了。
我并不是批评理论研究者,相反,作为一个实用主义者,我觉得真正沉下心去做理论研究的人是非常伟大的,无论究竟有没有出成果。我知道自己不是搞理论那块料,所以我对他们的敬佩尤甚:他们在理论方面的贡献是非常重要的,他们的工作对于推动科学的发展是不可或缺的。
我真正批评的是那些把理论研究中的某些方面过分强调、甚至用这些玩意来批评工程优良实践中的人。我不止一次见到过在C++做寄存器优化的人,也见过 std::array<int, N> 超时、连perf都不做就直接把这玩意改成 int* 的情况,更见过试图手写STL的情况。
那你说手动寄存器优化能不能做?理论上当然能啊,甚至能更快!
那你说 std::array<int, N> 和 int* 哪个更快?理论上当然后者更快啊!
那你说手写STL和标准库哪个更快?理论上当然是手写STL啊!
但是问题是你在哪个C++项目见到过真正需要手动寄存器优化、见到过 std::array<int, N> 性能不够、标准库性能不够的情况?
你的可读性哪里去了?你的可维护性哪里去了?你的安全性哪里去了?你的开发效率哪里去了?这些东西真的不重要吗?
性能优化固然是非常重要的,但它不是唯一重要的东西。实际上这就是所谓"数学*的搬运工"的典型表现之一,不分场合的过分强调理论,而忽视了实践中的其他重要因素。对于大多数的工程项目来说,性能优化并不是最重要的因素。
那有些人又要拿我上述这段话去批评之前那些过分强调理论的人了——殊不知这也是数学*的搬运工的行为:
你在Linux内核代码写寄存器优化,写得好不好?写得好啊!
但是你在一个普通的C++项目里写寄存器优化,写得好不好?写得不好啊!
那你说我是不喜欢理论吗?这边建议翻翻目录,整个第七节足足80页都在讲理论,甚至更多的地方中理论和实践都是穿插来的——实际上这些理论确实能够非常好的指导实践的过程。还是那句话:"理论指导实践,实践检验理论"。没有这些理论知识,系统设计、架构权衡、性能优化等实践确实是很难做的好的。
但你可别去背诵那玩意。
实践的第一要务自然是"实事求是"。"数学*的搬运工"们,放在以前,那叫"犯了形而上学的错误"。
于是,他们口中的"理论"变成了一坨符号化的东西,内部自洽、极为排他,但是没用。这坨东西,现在通常被称为"赢学"。
别把理论搞成了赢学,我说真的。
更要命的是,现在很多学校确实只看数学——恰恰在工程实践中,去背八股文、去替代计算机做运算,这些技能是被数学所宣传的,但实际上是最没用的。而这种人往往却被HR喜欢——然后在项目组里天天搞些高屋建瓴的工作,开会、做PPT时讲得头头是道,甚至在技术讨论中也能说得天花乱坠,但真正让他写代码的时候,可能就只能写出一些垃圾代码了。那么你说,这样的人能不能算是一个好的工程师?
我觉得不能。
我甚至敢说,在PKU信科随机挑选一个学生,问他 glibc 是什么(甚至都不用问实现细节),问他 origin/main 和 main 有什么关系,我猜没几个人能说出来。难道说这东西真是什么很高深的东西吗?不,这只是一个非常基础的东西,是每个计算机相关专业的学生都应该知道的东西。但为什么很多学生都不知道呢?
考试不考罢了!
是了。考试这指挥棒指挥了刚刚通过三年高中学习的学生们的学习方向。这些学生思维定势,来到大学之后想当然地让考试指挥自己的学习了——这又是学生们自己的问题了。大学本身确实是一个相对自由的环境,学生们可以选择自己想学的东西来学;但教师不加以引导,能快速转变思路、认识到相关实践的重要性的学生自然少之又少,能主动去实践的人就更少了。
在LCPU群里曾有群友吹水"能意识到《手册》重要性的同学,其技术能力都已经不需要《手册》了"。
目前看来还真是。
LLM时代怎么教、作业该怎么设计、怎么让学生真正去动手实践,其实我也不知道,这也确实是一个值得思考的问题。但是现在单按学校这种教法,纯考察理论的记忆、并要求学生把它默写下来,肯定是不行的了。我们似乎也不能一味的相信后人的智慧,改变应该从现在开始尝试了。
目前来看这本《手册》算是开了个头,我在《手册》里总是说"自己写一遍""Vibe的前提是自己会写",这都是希望同学们自己去实践,去动手写代码,去动手操作计算机,而不是仅仅停留在理论的层面上。因为只有通过实践,才能真正理解和掌握这些知识和技能,才能真正提升自己的能力。
虽说《手册》的内容和形式都还很不成熟,甚至可以说是很幼稚的了,但是至少也迭代了半年,也希望在后续的版本中能够不断改进。
发发牢骚,算是把近些年来的一些不满发泄出来了。
散会。
第二版前言¶
我们更应该关注那些不敢被问出的问题。
上面这句话是我和同学们讨论的时候,同学们提出来的。我觉得这句话非常有道理。
在过去的几个月里,我和一些同学们讨论了很多关于计算机基础教育的问题。我们发现,很多同学们在学习计算机基础知识时,往往会遇到一些"隐形的障碍",这些障碍并不是因为他们不够聪明或者不够努力,而是因为他们缺乏一些基本的知识和技能,这些知识和技能并没有被明确地教授出来。于是我写了这么个东西。
但是,很快,可能是我个人的能力有限,也有可能是我太过傲慢,《手册》很快变成我一个人的狂欢。我自己添加的内容:从C++的constexpr甚至consteval、到在《编程基础》出现的GPG密钥,再到我个人自作主张加上的多线程编程以及单纯为了方便自己写代码而加上的CMake,甚至是我个人觉得有趣的内容,比如说shell脚本编程、正则表达式、以及一些Linux下的高级操作等等,乃至Arch Linux传教,完全没有考虑到读者的接受能力和需求。结果就是,《手册》变得越来越厚重,越来越难以阅读,越来越难以理解。深度和广度上,我个人对《手册》有很大的满足感,但是对于读者来说,可能并不是这样。
但你让我删掉这些内容,我又觉得很难受。因为这些内容都是我个人觉得非常有用的东西。我觉得如果我不把这些东西写出来,那么读者就会错过很多有用的知识和技能。另一方面,我费了许多心思写出来的东西,如果没有人看,那我也觉得很可惜。
于是,在第二版手册中,我将会把整个手册劈成更多小节,这些小节不仅可以分开阅读,还可以放在一起从头到尾通读:
- 导航和方法——介绍在大学获取知识的方法和途径,帮助读者更好地利用手册和其他资源。这一章是必须要读的。
- 基础使用:让计算机先跑起来——介绍计算机的基本使用方法,帮助读者快速上手计算机。
- 终端和Linux基础:为开发铺垫语境——介绍Linux和终端的基础知识,帮助读者理解计算机的工作原理。
- 开发环境:让代码能编译能跑——介绍编程环境的搭建和使用、C/C++、Python的语法、包、编译工具链等内容,帮助读者快速进入编程状态。
- 实用主义编程:写出更好的代码——介绍实用主义编程的理念和方法以及相关工具,如git、密钥等,帮助读者提高编程效率和代码质量,促进更好的协作。
- 原理速览:知其然,更知其所以然——介绍计算机的基本原理,帮助读者理解计算机的工作机制。
- 工具箱——介绍一些实用的工具和技巧,帮助读者更好地使用计算机。
- 延伸进阶阅读——介绍一些进阶的知识和技能,帮助读者进一步提升自己的能力。
我想要的从来就不是名义上的"厚重",而是实实在在的"有用"。我希望读者们能够从《手册》中获得真正有用的知识和技能,而不是被一些无关紧要的内容所淹没。我希望读者们是真的不会被"overwhelmed"。
阅读路径提示
所有标注为"进阶阅读"的章节都是可选的,读者可以根据自己的兴趣和需求选择是否阅读。
也正因此,本书有多种阅读方式,满足不同读者的需求。在读完第一节"导航与方法"之后,读者可以根据自己的需求选择不同的阅读路径。我希望读者能先阅读目录,再选择性的阅读想看的内容。
我给出以下几个参考路径:
- 之前完全没接触过计算机,希望能自己装个软件、写个Hello World:
- 入门认知:学会怎么用键盘、怎么管理文件;
- 系统和软件:学会装个软件;
- 编程入门:配好开发环境;
-
写第一个程序:写出第一个Hello World。
-
希望能简单学点脚本,写点小程序,能用Git管理代码和论文,用LaTeX等工具写点东西:
- 入门认知:学会装个软件,学会怎么用键盘、怎么管理文件;
- 写作工具:学会用LaTeX写论文;
- 脚本自动化:学会用Python写点小程序、脚本,能画出漂亮的数据分析图表;
-
版本管理:学会用Git管理代码和论文,防止写坏或丢失。
-
希望能写脚本、画图、跑模型,用Linux做实验,能用Git管理代码和论文:
- 快速上手:学会VS Code写Python、虚拟环境装包跑脚本;
- 写作工具:学会用LaTeX等工具写论文;
- 数据处理:学会用Python写点小程序、脚本,能画出漂亮的数据分析图表;
- Linux环境:学会用Linux做实验,会用终端加速工作;
-
进阶玩法:学会用Git管理代码和论文,防止写坏或丢失,也能把别人的代码拿下就跑起来。
-
计算机相关专业学生:我认为应该通读大部分
- 基础打底:学会Linux、终端、WSL等基础知识,为后续开发打好基础;
- 编程入门:学会配VS Code、调试、写C/C++和Python,能写出较高质量的代码;
- 工程能力:学会写CMake,用Git,多人协作;
- 系统原理:即使不学ICS,作为信科学生也应该了解计算机的基本原理;
-
进阶玩法:学会远程开发、签名、调试等进阶工程技能。
-
OIer快速过渡到大学工程开发环境,避免"只会写算法不会写项目":
- 环境过渡:学会用VS Code写现代的C++,学会用CMake管理项目,杜绝Fake C++(C with classes);
- 工程规范:学会用Git管理代码,学会调试程序、规范代码,提升代码质量;
- 走向Linux:学会在Linux下开发,学会远程开发,适应大学的开发环境;
-
进阶可选:了解计算机的基本原理和多线程编程。这前提是你想打底层、系统或科研,或者更先进的算法竞赛(如HPC竞赛)。
-
纯装机,想买台新电脑,希望一条龙搞好新机、配好开发环境: 下午拿到新电脑,晚上就搞好开发环境,第二天就能提着新电脑去上课。
-
有篇论文想投稿,内容都想好了,但不会用LaTeX排版: 学会用LaTeX写论文,搞定投稿格式,一周学完语法,顺便论文也排好。
-
"先跑AI再说"极速路线: miniconda - PyTorch - Pandas - Docker轻量化,搞定AI环境,直接跑模型。
希望第二版会比第一版对同学们更有帮助。
如有疑问、意见或建议,欢迎来该项目的仓库 :github: ZangXuanyi/getting-started-handout 查看本手册的源代码,欢迎提出Issue与Pull Request。如不能访问,也可向我发送电子邮件咨询(见封面)。也可加入该手册的官方讨论群聊(QQ群号:1059423771)。
第一版前言¶
计算机基础科学教育是我国近些年一直努力推进的教育之一,北京大学的所有学生都应修习《计算概论》课程。然而,大学计算机基础教育的内容往往过于理论化,缺乏实用性,这使得同学们在学习过程中容易感到枯燥乏味,在学习之后也很难将所学知识灵活应用到实际生产与生活中,最终导致在校学生对计算机的使用和开发能力普遍较低,甚至出现了"念了四年本科却不会用Git"的现象。同时,我国初高中乃至小学阶段,计算机的教育水平参差不齐,同学们的基础也不尽相同,这导致部分基础较差的同学在学习《计算概论》时会遇到困难,遑论进阶课程。
在本手册正式编写之前,已经有很多学长为了抹平基础知识的差距做出了相关的努力。几个广为人知的项目:北京大学为新生提供了《计算概论衔接课》,旨在帮助同学们快速入门计算机基础知识(这门课的前半部分由我所讲授);北京大学学生Linux俱乐部(LCPU)启动了 Getting Started项目 ,旨在帮助同学们快速入门Linux和计算机科学(该项目亦由我全权负责);一位 :github: 学长 发起了 CS自学指南 项目,受到了广泛的关注和认可,该项目迄今已有一百五十余位贡献者;PKUHub等其他官方或非官方的组织也在积极推动计算机基础教育的普及。
然而,Getting Started和自学指南对于大一新生而言,存在的最大不足之处就是:不够基础。而对于有能力就读北大的学生而言,"上课"这种获取信息的形式的信息密度显然是不够的,大约是已经不再幻想上课有用了;真正有用的知识还是要靠同学们自己去学习实践。因此,我认为给同学们一本手册要比给同学们数小时的课程视频有用得多。笔者最终决定:制作这份手册,帮助同学们把初高中缺失的计算机知识,以及大学丢失的开发能力补回来。
本手册可以认为是对大学常用计算机基础知识与基础开发能力的汇总,比起深度更注重广度,比起理论更注重实践。简而言之,我们手册中会讲一些正课几乎不会讲、但是用处极大的知识。我们认为使用本手册的同学都已经具备了最基本的计算机操作能力,例如"使用鼠标""关机"这种操作默认大家非常熟练,因此也不会涉及相关内容。
本手册正文分为两部分。第一部分面向计算机新手,讲述计算机基础知识,内容涵盖计算机组成和使用、编程环境配置、文本处理、Linux等内容,旨在将同学们的水平提升至能够接受大学计算机基础教育的水平;第二部分则面向工程开发新手,讲述工程开发的一些基础内容,包含C++和Python的语法基础、实用主义编程、调试和C语言工具链等,旨在将同学们的水平提升至能够进行简单工程开发的水平。
本文偏理论的章节中有一些"开放性思考和探索"板块,使用黄色背景色标注,旨在引导同学们进行更深入的思考和探索。笔者仅仅提供一些选题供参考,自己也不知道有没有一个确定的答案以及答案是什么,因此也不会给出答案甚至思路。有兴趣、有技术的同学们可以自行探索相关话题,甚至可以作为大作业、数学建模、科创甚至毕业设计的选题种子。当然,如果觉得难度过高,也完全可以跳过。
本手册以本人实践和经验为基底讲授。如果本手册中的内容和正课中的内容或要求有差异,请以正课为准。
本手册参考了LCPU Getting Started以及诸多博文、指南的内容,并在此基础上进行了增删和修改。
希望本手册能够对同学们有所帮助。
