了解你的局限
“人要知道他自己的局限。”——警探哈里
你的资源是有限的。你只有这些时间和金钱来工作,包括需要用于保持知识、技能和工具跟上时代的时间和金钱。你只能工作到这样努力,这样快,这样聪明,这样长的时间。你的工具也只能这样强大。你的目标机器也只能这样强大。所以,你必须重视你的资源的局限。
如何重视这些局限呢?了解自己,了解别人,了解预算,了解事物。特别地,一个软件工程师,要了解自己的数据结构和算法的空间和时间复杂度。你的工作是对软件和系统创建一个最佳匹配。
空间和时间复杂度是通过n趋近于无穷时的函数O(f(n))给出的,其中n等于输入的空间或时间的近似大小。重要的f(n)包括ln(n),n,nln(n),ne和en.
你的资源是有限的。你只有这些时间和金钱来工作,包括需要用于保持知识、技能和工具跟上时代的时间和金钱。你只能工作到这样努力,这样快,这样聪明,这样长的时间。你的工具也只能这样强大。你的目标机器也只能这样强大。所以,你必须重视你的资源的局限。
如何重视这些局限呢?了解自己,了解别人,了解预算,了解事物。特别地,一个软件工程师,要了解自己的数据结构和算法的空间和时间复杂度。你的工作是对软件和系统创建一个最佳匹配。
空间和时间复杂度是通过n趋近于无穷时的函数O(f(n))给出的,其中n等于输入的空间或时间的近似大小。重要的f(n)包括ln(n),n,nln(n),ne和en.
重要的f(n)
如图中所示,随着n的增长,O(ln(n))远远小于O(n)和O(n ln(n)),后两者又远远小于O(ne)和O(en)。正如Sean Parent所述,对于可到达的n,所有的复杂度可分为近似常量、近似线性和近似无穷。
复杂度分析是依照虚拟机器的,但软件是在实际机器上运行的。现代计算机系统已优化为物理机和虚拟机的层次,包括语言运行时,操作系统,CPU,缓存,随机访问存储器,硬盘和网络。第一张表显示了一个英武的网络服务器的随机访问时间和容量。
| access time | capacity |
register | < 1 ns | 64 b |
cache line |
| 64 B |
L1 cache | 1 ns | 64 KB |
L2 cache | 4 ns | 8 MB |
RAM | 20 ns | 8 MB |
disk | 10 ms | 10 TB |
LAN | 20 ms | > 1 PB |
Internet | 100 ms | > 1 ZB |
注意容量和速度的数量级变化的几个顺序。缓存和先行预测在我们系统的每一层大量使用以隐藏这种变化,但它们只在访问可预测时有用。当缓存不能命中时,系统就会抖动。例如,随机地查看硬盘上的每个字节可能需要32年,即使是随机查看RAM中的每个字节也可能需要11分钟。随机访问是不可预测的。什么意思?它由系统决定,但再次访问近期访问过的条目或者相邻的条目则会很有效。
算法和数据结构在如何有效地使用缓存方面大不相同。比如:
· 线性查找有效地使用了先行预测,但需要O(n)次比对。
· 二分查找一个已排序的数组只需要O(log(n))次比对。
· 查找一个van Emde Boas树是O(log(n))并且缓存未知。
如何选择呢?最近的分析是通过测量。第二张表显示了通过这三种方法查找64位整数数组所需的时间。在我的电脑上:
算法和数据结构在如何有效地使用缓存方面大不相同。比如:
· 线性查找有效地使用了先行预测,但需要O(n)次比对。
· 二分查找一个已排序的数组只需要O(log(n))次比对。
· 查找一个van Emde Boas树是O(log(n))并且缓存未知。
如何选择呢?最近的分析是通过测量。第二张表显示了通过这三种方法查找64位整数数组所需的时间。在我的电脑上:
|
| |||
8 | 50 | 90 | 40 | |
64 | 180 | 150 | 70 | |
512 | 1200 | 230 | 100 | |
4096 | 17000 | 320 | 160 | |
| Linear | Binary | vEB |
· van Emde Boas无疑是赢家,凭借它的可预测的访问模式。
“付你要的钱,选你要的东西。”—— Punch