学习的目的和方法论(实战主义)

该文来自知乎,因为与个人的学习方法和态度非常一致,特转载。希望广大软件开发工程师在技术变更较快的情况下,依然能屹立在时代之巅。

原文来自:http://www.zhihu.com/question/22608820  。

首先是学习的目地,这里以操作系统以及计算机体系结构为例:

学习操作系统的目的,不是让你去发明自己操作系统内核,打败 Linux;也不是成为内核开发人员;而是理解操作系统为用户态进程提供了怎样的运行环境,作为程序员应该如何才能充分利用好这个环境,哪些做法是有益的,哪些是做无用功,哪些则是帮倒忙。

学习计算机体系结构的目的,不是让你去设计自己的 CPU(新的 ISA 或微架构),打败 Intel 和 ARM;也不是参与到 CPU 设计团队,改进现有的微架构;而是明白现代的处理器的能力与特性(例如流水线、多发射、分支预测、乱序执行等等指令级并行手段,内存局部性与 cache,多处理器的内存模型、能见度、重排序等等),在编程的时候通过适当组织代码和数据来发挥 CPU 的效能,避免 pitfalls。Modern Microprocessors

接着是学习的方法论:

这两门课程该如何学?看哪些书?这里我告诉你一个通用的办法,去美国计算机系排名靠前的大学的课程主页,找到这两门课最近几年的课程大纲、讲义、参考书目、阅读材料、随堂练习、课后作业、编程实验、期末项目等,然后你就心里有数了。

学习任何一门课程都要善于抓住主要矛盾、分清主次、突出重点,关键是掌握知识框架,学会以后真正有用的知识和技能,而不要把精力平均分配在一些琐事上。

请允许我再次引用孟岩的观点:http://blog.csdn.net/myan/article/details/5877305

我(孟岩)主张,在具备基础之后,学习任何新东西,都要抓住主线,突出重点。对于关键理论的学习,要集中精力,速战速决。而旁枝末节和非本质性的知识内容,完全可以留给实践去零敲碎打。

原因是这样的,任何一个高级的知识内容,其中都只有一小部分是有思想创新、有重大影响的,而其它很多东西都是琐碎的、非本质的。因此,集中学习时必须把握住真正重要那部分,把其它东西留给实践。对于重点知识,只有集中学习其理论,才能确保体系性、连贯性、正确性,而对于那些旁枝末节,只有边干边学能够让你了解它们的真实价值是大是小,才能让你留下更生动的印象。如果你把精力用错了地方,比如用集中大块的时间来学习那些本来只需要查查手册就可以明白的小技巧,而对于真正重要的、思想性东西放在平时零敲碎打,那么肯定是事倍功半,甚至适得其反。

因此我对于市面上绝大部分开发类图书都不满——它们基本上都是面向知识体系本身的,而不是面向读者的。总是把相关的所有知识细节都放在一堆,然后一堆一堆攒起来变成一本书。反映在内容上,就是毫无重点地平铺直叙,不分轻重地陈述细节,往往在第三章以前就用无聊的细节谋杀了读者的热情。

比如说操作系统,应该把精力主要放在进程管理与调度、内存管理、并发编程与同步、高效的IO等等,而不要过于投入到初始化(从 BIOS 加载引导扇区、设置 GDT、进入保护模式)这种一次性任务上。我发现国内讲 Linux 内核的书往往把初始化的细节放在前几章,而国外的书通常放附录,你可以体会一下。初始化对操作系统本身而言当然是重要的,但是对于在用户态写服务程序的人来说,弄清楚为什么要打开 PC 上的 A20 地址线真的有用处吗?(这不过是个历史包袱罢了。)

再比方说《计算机网络》,关键之一是理解如何在底层有丢包、重包、乱序的条件下设计出可靠的网络协议,这不算难。难一点的是这个可靠协议能达到“既能充分利用带宽,又能做到足够公平(并发连接大致平均分享带宽)”。而不是学会手算 CRC32,这更适合放到信息论或别的课程里去讲。

最后是学习的注意点:

注意分清知识的层次。就好比造汽车与开汽车的区别,我认为一个司机的技能主要体现在各种道路条件和天气状况下都能安全驾驶(城市道路、高速公路、乡间公路 X 晴、雨、雪、雾),平安到达目的地。作为一名司机,了解汽车运行的基本原理当然是好事,可以有助于更好地驾驶和排除一些常见故障。但不宜喧宾夺主,只要你不真正从事汽车设计工作,你再怎么研究发动机、传动、转向,也不可能比汽车厂的工程师强,毕竟这是人家的全职工作。而且钻研汽车构造超过一定程度之后,对开好车就没多大影响了,成了个人兴趣爱好。“有的人学着学着成了语言专家,反而忘了自己原本是要解决问题来的。”(语出孟岩 快速掌握一个语言最常用的50%

对于并发编程来说,掌握 mutex、condition variable 的正确用法,避免误用(例如防止 busy-waiting 和 data race)、避免性能 pitfalls,是一般服务端程序员应该掌握的知识。而如何实现高效的 mutex 则是 libc 和 kernel 开发者应该关心的事,随着硬件的发展(CPU 与内存之间互联方式的改变、核数的增加),最优做法也随之改变。如果你不能持续跟进这一领域的发展,那么你深入钻研之后掌握的知识到了几年之后可能反而成为累赘,当年针对当时硬件的最优特殊做法(好比说定制了自己的 mutex 或 lock-free 数据结构)在几年后有可能反而会拖低性能。还不如按最清晰的方式写代码,利用好语言和库的现成同步设施,让编译器和 libc 的作者去操心“与时俱进”的事。

注意识别过时的知识。比方说《操作系统》讲磁盘IO调度往往会讲电梯算法,但是现在的磁盘普遍内置了这一功能(NCQ),无需操作系统操心了。如果你在一个比较好的学校,操作系统课程的老师应该能指出这些知识点,避免学生浪费精力;如果你全靠自学,我也没什么好办法,尽量用新版的书吧。类似的例子还有《计算机体系结构》中可能会讲 RISC CPU 流水线中的 delay slot,现在似乎也都废弃了。《计算机网络》中类似的情况也不少,首先是 OSI 七层模型已经被证明是扯淡的,现在国外流行的教材基本都按五层模型来讲(Internet protocol suite),如果你的教材还郑重其事地讲 OSI (还描绘成未来的希望),扔了换一本吧。其次,局域网层面,以太网一家独大(几乎成了局域网的代名词),FDDI/Token ring/ATM 基本没啥公司在用了。就说以太网,现在也用不到 CSMA/CD 机制(因为 10M 的同轴电缆、10M/100M 的 hub 都过时了,交换机也早就普及了),因此碰撞检测算法要求“以太网的最小帧长大于最大传播延迟的二倍”这种知识点了解一下就行了。

另外一点是 low level 优化的知识非常容易过时,编码时要避免过度拟合(overfitting)。比方说目前国内一些教科书(特别是大一第一门编程语言的教程)还在传授“乘除法比加减法慢、浮点数运算比整数运算慢、位运算最快”这种过时的知识。现代通用 CPU 上的实际情况是整数的加减法和乘法运算几乎一样快,整数除法慢很多;浮点数的加减法和乘法运算几乎和整数一样快,浮点数除法慢很多。因此用加减法代替乘法(或用位运算代替算术运算)不见得能提速,反而让代码难懂。而且现代编译器可以把除数为小整数的整数除法转变为乘法来做,无需程序员操心。(目前用浮点数乘法代替浮点数除法似乎还是值得一做的,例如除以10改为乘以0.1,因为浮点运算的特殊性(不满足结合律和分配率),阻止了编译器优化。)

类似的 low level 优化过时的例子是早年用汇编语言写了某流行图像格式的编解码器,但随着 CPU 微架构的发展,其并不比现代 C 语言(可能用上 SIMD)的版本更快,反而因为使用了 32-bit 汇编语言,导致往 64-bit 移植时出现麻烦。如果不能派人持续维护更新这个私有库,还不如用第三方的库呢。现在能用汇编语言写出比 C 语言更快的代码几乎只有一种可能:使用 CPU 的面向特定算法的新指令,例如 Intel 的新 CPU (将会)内置了 AES、CRC32、SHA1、SHA256 等算法的指令。不过主流的第三方库(例如 OpenSSL)肯定会用上这些手段,及时跟进即可,基本无需自己操刀。(再举一个例子,假如公司早先用汇编语言写了一个非常高效的大整数运算库,一直运转良好,原来写这个库的高人也升职或另谋高就了。Intel 在 2013 年发布了新微架构 Haswell,新增了 MULX 指令,可以进一步提高大整数乘法的效率 GMP on Intel Haswell ,那么贵公司是否有人持续跟进这些 CPU 的进化,并及时更新这个大整数运算库呢?或者直接用开源的 GMP 库,让 GMP 的作者去操心这些事情?)

如果你要记住结论,一定要同时记住前提和适用条件。在错误的场合使用原本正确的结论的搞笑例子举不胜举。

  1. 《Linux内核源码情景分析》上分析内核使用 GDT/LDT 表项的状况,得出进程数不超过 4090 的结论。如果你打算记住这个结论,一定要记住这是在 Linux 2.4.0 内核,32-bit Intel x86 平台上成立,新版的内核和其他硬件平台很可能不成立。看完书后千万不要张口就来“书上说 Linux 的最大进程数是 4090”。
  2. 一个 Linux 进程最多创建 300 余个线程,这个结论成立的条件是 3GB 用户空间,线程栈为 10M 或 8M。在 64-bit 下不成立。
  3. Reactor 模式只能支持不超过 64 个 handle,这个结论成立的条件是 Windows 下使用 WaitForMultipleObjects 函数实现的 WFMO_Reactor,对于 Linux 下使用 poll/epoll 实现的 Reactor 则无此限制。
  4. C++ STL 的 vector 容器在 clear() 之后不会释放内存,需要 swap(empty vector),这是有意为之(C++11 里增加了 shrink_to_fit() 函数)。不要记成了所有 STL 容器都需要 swap(empty one) 来释放内存,事实上其他容器(map/set/list/deque)都只需要 clear() 就能释放内存。只有含 reserve()/capacity() 成员函数的容器才需要用 swap 来释放空间,而 C++ 里只有 vector 和 string 这两个符合条件。

最后一点小建议,服务端开发这几年已经普及 64-bit 多核硬件平台,因此在学习操作系统的时候,可以不必太关心单核上特有的做法(在单核时代,内核代码进入临界区的办法之一是关中断,但到了多核时代,这个做法就行不通了),也不必太花精力在 32-bit 平台上。特别是 32-bit x86 为了能支持大内存,不得已有很多 work around 的做法(困难在于 32-bit 地址空间不够将全部物理内存映射入内核),带来了额外的复杂性,这些做法当时有其积极意义,但现在去深入学似乎不太值得。

时间: 2024-11-07 01:05:54

学习的目的和方法论(实战主义)的相关文章

@程序员,这四个学习建议值得收藏

在我看来,学习能力应该是一个人最重要的能力之一.因为我们赖以生存的所有技能,无一例外都是通过学习获得的.那些优秀的人,也不过是学习能力或者学习效率比一般人强而已. 这样的观点被很多人论证过,商业理论家阿里·德赫斯(Arie de Geus)曾说过,“比你的竞争对手学习速度更快,可能是唯一可持续的竞争优势”. 如今,IT 技术更新日新月异,不论是新版本的更新还是新框架的产生,都以极快的速度在推进,令人眼花缭乱,应接不暇.因此,对程序员来说,持续学习.有选择地学习显得尤为重要. 01.多角度,对比学

周鸿祎《智能主义》读书笔记

第一章:智能主义     在周鸿祎看来,计算机和互联网的这几十年的发展带来的最令人兴奋的变革.发现最令人兴奋的变革发生在人工智能和大数据领域,可以预见的是人工智能与大数据的完美结合,将开启新一轮的发展高潮,我们或将迈入智能时代.     下一个五年.对于互联网和移动互联网安全来说,最大的威胁和挑战,来自于物联网技术带来的第四次工业革命. 在互联网时代,安全隐患带来的问题可能是信息的泄露,而在物联网时代,安全隐患带来的危害可能是致命的,比如说智能汽车被黑客控制. 关于智能硬件,作者认为,因为智能硬

2天驾驭DIV+CSS (实战篇)(转)

这是去年看到的一片文章,感觉在我的学习中,有不少的影响.于是把它分享给想很快了解css的兄弟们.本文是实战篇. 基础篇[知识一] “DIV+CSS” 的叫法是不准确的[知识二] “DIV+CSS” 将你引入两大误区[知识三] 什么是W3C标准?[基础一] CSS如何控制页面[基础二] CSS选择器[基础三] CSS选择器命名及常用命名[基础四] 盒子模型[基础五] 块状元素和内联元素 实战篇[第一课] 实战小热身[第二课] 浮动[第三课] 清除浮动[第四课] 导航条(上) | 导航条(下)[大练

《国际项目集管理最佳实践与实战应用》大型复杂项目与项目群管理工作坊

<国际项目集管理最佳实践与实战应用>大型复杂项目与项目群管理工作坊 Program Management Training 主办单位:共创国际-项目管理者联盟 2015年4月10.11.12日 北京 & 课程前言 项目集(PROGRAM)定义为“经过协调管理以获取单独管理它们时无法取得收益与控制的一组关联的项目和项目集活动.”从组织战略的角度来看,项目集管理主要是指组织为实现其战略目标或为其客户提供整体解决方案而在组织高层针对战略性资源进行跨界整合的管理活动. 在全球经济一体化的背景下

企业级业务系统开发实战

通过一个系列讲述一个真实企业的ERP系统开发全过程.其中包括需求分析.设计建模.开发.测试全生命周期过程,其中会详细讲方法论与技术实践.涉及到的方法包括敏捷软件开发.四色原型.领域驱动设计.业务架构.技术架构与具体的EF.WF.EasyUI等技术在项目中的使用. 领域驱动设计案例之领域层框架搭建 摘要: 根据前面对领域驱动设计概念以及一些最佳实践的理解,领域模型是系统最核心的部分,我们还是采用前面销售订单的例子,这个案例系统的核心构建就从领域层开始.领域层框架搭建主要完成两个任务:1.领域模型的

IT行业卓越的目标与绩效管理高级研讨课程大纲 (两天实战版)

IT行业卓越的目标与绩效管理高级研讨课程大纲 (两天实战版) (如欲公开以下内容,或者需对大纲作专业化调整,请与本人联系确认) [课程关键词]绩效管理循环.工作计划.MBO\KPI\BSC.企业文化 [课程时长]2天(估计每天6.5小时) [课程对象]企业领导者,部门经理.其他各级经理和主管 [课程形式] 演讲,问题讨论和个案分析. 问题讨论和个案分析将与授课紧密结合. 授课现场需准备投影仪,电源拖板,学员用胶贴纸,铅笔和练习纸,如再配白板和白板水笔更好. 采用了电影剪辑和情境片断等多媒体培训技

第2章 传统与敏捷方法论

2.1  传统泛瀑布软件开发模式 2.1.1  瀑布模式 1.瀑布模式简介 2.瀑布模式特色 3.瀑布模式缺点 2.1.2  渐增模式 1.渐增模式简介 2.渐增模式特色 3.渐增模式缺点 2.1.3  雏形模式 1.雏形模式简介 2.雏形模式特色 3.雏形模式缺点 2.1.4  螺旋模式 1.螺旋模式简介 2.螺旋模式特色 3.螺旋模式缺点 2.1.5  统一开发过程模式 1.RUP模式简介 2.RUP模式特色 3.RUP模式缺点 2.2  敏捷方法论 2.2.1  Scrum 1.Scrum

MATLAB数据分析与挖掘实战

这篇是计算机中数据库存储与管理类的优质预售推荐<MATLAB数据分析与挖掘实战>. 多位资深数据挖掘专家10余年实战经验结晶,深入讲解数据挖掘各个环节的各项技术. 编辑推荐 通过10余个真实的案例为10余个行业的数据挖掘提供了解决方案,并提供相关的建模文件和源代码. 前言部分  为什么要写这本书 LinkedIn 对全球超过3.3亿用户的工作经历和技能进行分析后得出,在目前最炙手可热的25项技能中,数据挖掘人才需求排名第一.那么数据挖掘是什么? 数据挖掘是从大量数据(包括文本)中挖掘出隐含的.

交通行业卓越的目标与绩效管理高级研讨课程大纲(三天实战版)

交通行业卓越的目标与绩效管理高级研讨课程大纲 (三天实战版) (如欲公开以下内容,或者需对大纲作专业化调整,请与本人联系确认) [课程关键词]绩效管理循环.工作计划.MBO\KPI\BSC.企业文化 [课程时长]3天(估计每天6.5小时) [课程对象]企业领导者,部门经理.其他各级经理和主管 [课程形式] 演讲,问题讨论和个案分析. 问题讨论和个案分析将与授课紧密结合. 授课现场需准备投影仪,电源拖板,学员用胶贴纸,铅笔和练习纸,如再配白板和白板水笔更好. 采用了电影剪辑和情境片断等多媒体培训技