一、补码:负数在计算机里如何表示?
计算机底层只认识二进制。
整数通常以固定长度存储,比如 32 位或 64 位。
对于有符号整数,最高位通常表示符号:
0 表示非负数
1 表示负数
现代计算机通常使用补码表示负数。
以 8 位为例:
0000 0001 表示 1
1111 1111 表示 -1
1111 1110 表示 -2
补码的好处是:计算机可以用同一套加法规则处理正数和负数。
例如:
0000 0001 1
1111 1111 -1
---------
0000 0000 0
最高位溢出被丢弃后,结果就是 0。
这就是补码的优雅之处。
二、Python 的变量:名字是标签,对象才是本体
Python 里的变量,不是一个固定盒子。
它更像是贴在对象上的标签。
a = 10
b = a
a = 20
执行过程可以理解为:
1. 创建整数对象 10
2. a 指向 10
3. b 也指向 10
4. 创建整数对象 20
5. a 改为指向 20
6. b 仍然指向 10
所以:
print(a) # 20
print(b) # 10
Python 中更准确的理解是:
变量名绑定对象
而不是:
变量名就是一块固定内存
三、可变对象和不可变对象
Python 对象可以大致分为两类。
不可变对象:
int
float
str
tuple
bool
可变对象:
list
dict
set
不可变对象不能在原地修改。
例如:
a = 10
a = 20
这里不是把原来的整数 10 改成了 20,而是让 a 指向了新的整数对象 20。
可变对象可以在原地修改。
a = [1, 2, 3]
b = a
a.append(4)
print(b)
输出:
[1, 2, 3, 4]
原因是 a 和 b 指向同一个列表对象。
append() 修改的是这个列表对象本身,所以两个变量都能看到变化。
这也是二维列表浅拷贝问题的根源。
四、C++ 的变量:更像固定盒子
C++ 的普通变量更接近“固定内存盒子”。
int a = 10;
int b = a;
a = 20;
可以理解为:
1. 给 a 分配一个 int 盒子,里面放 10
2. 给 b 分配另一个 int 盒子,把 a 的值复制过去
3. 把 a 盒子里的内容改成 20
4. b 的盒子不受影响
所以 C++ 里的普通变量更贴近硬件内存模型。
Python 偏“对象引用和名字绑定”。
C++ 偏“内存位置和数值写入”。
五、Python vs C++:两种变量哲学
可以这样对比:
Python 的好处是写起来灵活、抽象程度高。
C++ 的好处是更贴近硬件,性能和控制力更强。
理解这点之后,很多语言差异就会变得非常清晰。
六、PyPy3 和 CPython:为什么 OJ 上表现不一样?
刷题时经常会看到:
Python3
PyPy3
大多数情况下,Python3 指的是 CPython。
CPython 是最常见、最标准的 Python 实现。
它的特点是:
启动快
兼容性好
行为稳定
解释执行
PyPy3 的特点是 JIT,也就是即时编译。
它会在程序运行时观察哪些代码执行得最频繁,然后把这些热点代码编译成更高效的机器码。
所以在大量循环、大规模计算时,PyPy3 可能比 CPython 快很多。
但是 PyPy3 不一定总是赢。
因为 JIT 本身也有成本:
需要观察热点代码
需要编译
需要维护机器码缓存
启动和热身成本更高
内存占用可能更大
所以小数据量题目里,PyPy3 可能还没热身完,程序已经结束了。
这时 CPython 反而可能更快、更省内存。
可以这样记:
CPython 像轻装短跑选手
PyPy3 像带装备的长跑选手
短跑时,装备是负担。
长跑时,装备才发挥优势。
七、大模型 Self-Attention:为什么长上下文贵?
大语言模型的核心机制之一是 Self-Attention。
它的基本直觉是:
每个 token 都要和上下文里的其他 token 建立关系
如果上下文长度是 N,那么 token 两两关系大致是:
N × N
所以标准 Self-Attention 的复杂度通常是:
O(N²)
注意,这是平方复杂度,不是指数复杂度。
但平方复杂度已经非常可怕。
当上下文长度从 1,000 增加到 10,000,长度增加 10 倍,注意力计算量可能接近增加 100 倍。
这就是为什么长上下文模型非常吃算力。
八、KV Cache:大模型里的空间换时间
大模型生成文本时,是一个 token 一个 token 生成的。
如果每生成一个新 token,都重新计算前面所有 token 的信息,会非常浪费。
所以工程上会使用 KV Cache。
可以粗略理解为:
把之前已经算过的 Key 和 Value 缓存起来,后面直接复用
这样生成新 token 时,就不必从头重复计算整个上下文。
优点:
生成速度更快
减少重复计算
长文本生成更现实
代价:
占用大量显存
上下文越长,占用越大
batch 越大,占用越大
所以 KV Cache 的本质就是:
空间换时间
这和算法里的缓存、哈希表、动态规划数组,本质上是同一种思想。
九、把所有知识串起来:时间、空间、引用、缓存
无论是 Python 变量、C++ 内存,还是大模型 KV Cache,它们背后的核心问题都很相似。
你永远可以问这几个问题:
数据在哪里?
谁指向它?
有没有复制?
修改的是对象,还是换了引用?
为了更快,付出了多少空间?
为了更省空间,又牺牲了多少时间?
这些问题,就是理解计算机系统的底层抓手。
十、总结
这一篇的核心不是某个具体语法,而是建立底层世界观。
真正理解计算机,不只是记住“这个 API 怎么用”。
更重要的是看见代码背后的东西:
内存、对象、引用、复制、缓存、复杂度,以及时间和空间之间永远存在的交换。
当你开始用这些问题去看代码,就说明你已经从“会写语法”,进入了“理解系统”的阶段。
从 Python 变量到 C++ 内存,再到大模型 KV Cache:理解计算机的底层世界观
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法