# 1. 命令式编程(Imperative Programming)
# 核心思想
- 按顺序执行每条语句,每执行一步就会改变程序的状态。
- Python 就是典型的解释型语言,执行代码时会 逐行运行。
# 示例
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
执行过程:
e = add(a, b)→ 计算 1+2 = 3,并存到变量ef = add(c, d)→ 计算 3+4 = 7,并存到变量fg = add(e, f)→ 计算 3+7 = 10- 返回并打印结果
10
特点:
- 直观易懂,方便调试。
- 每次函数调用都需要解释器处理,效率不高(尤其是在 GPU 上运行大批量计算时)。
# 2. 符号式编程(Symbolic Programming)
# 核心思想
-
先定义整个计算图/计算流程,再一次性执行。
-
可以让编译器提前做优化,例如:
- 合并重复计算
- 直接生成最优机器指令
- 提前释放不再需要的内存
# 示例(模拟)
prog = """
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
"""
y = compile(prog, '', 'exec') # 编译成可执行代码
exec(y) # 一次性运行
特点:
- 运行更快,可以做优化
- 可以生成与 Python 无关的可执行代码,更容易移植。
- 调试不如命令式方便。
# 3. 混合式编程(Hybrid Programming)
# 背景
-
很多深度学习框架历史上在命令式和符号式之间选择:
- TensorFlow 1.x:符号式
- PyTorch:命令式
-
混合式编程的出现是为了 兼顾易用性和性能:
- 开发时用命令式调试方便
- 部署时用符号式优化和移植方便
# PyTorch 示例:torch.jit
import torch
from torch import nn
# 定义网络
net = nn.Sequential(
nn.Linear(512, 256),
nn.ReLU(),
nn.Linear(256, 128),
nn.ReLU(),
nn.Linear(128, 2)
)
x = torch.randn(1, 512)
net(x) # 命令式执行
# 转换为符号式/优化版本
net = torch.jit.script(net)
net(x) # 编译后的网络,效率更高
-
torch.jit.script会把命令式网络转换成 静态计算图,实现:- 编译优化
- 在 GPU 上高效运行
- 可导出为非 Python 环境使用
# 4. 总结对比
| 编程方式 | 优点 | 缺点 | 示例框架 |
|---|---|---|---|
| 命令式 | 易懂、易调试 | 运行慢,难优化 | PyTorch |
| 符号式 | 高效,可优化,易移植 | 调试不方便 | TensorFlow 1.x, Theano |
| 混合式 | 易调试 + 高效部署 | 需要额外转换步骤 | PyTorch + torch.jit, TensorFlow 2.x |
理解:
- 命令式:边写边运行
- 符号式:先写完整程序再运行
- 混合式:平时用命令式调试,部署用符号式加速
