ai-infra-interview-305

第 2 题:torch.nn.Module的__call__和forward有什么区别?为什么要这样设计?

题目

torch.nn.Module的__call__和forward有什么区别?为什么要这样设计?


完整讲解

一、调用链:你写的是 __call__,实际算的是 forward

用户写的是 model(x),Python 会调用 model.__call__(x)。nn.Module 的 __call__ 内部会做一堆前后处理,最后再调 self.forward(x)。所以:

一句话:__call__ = 框架层壳子,forward = 你写的数学/计算。


二、__call__ 里通常做了哪些事?

(以常见 PyTorch 实现为准,细节可能随版本略有差异。)

  1. 多次 forward 检查:防止在已执行的 forward 里再次触发 forward(递归调用导致图错乱)。
  2. 调用 before / after forward hook:forward_pre_hook、forward_hook,便于调试、可视化、插层。
  3. 真正执行:result = self.forward(*input, **kwargs)。
  4. 类型与设备:有的封装会保证输入/输出类型一致、放到正确设备。

所以若子类重写 __call__ 而不调 forward,或改了调用顺序,hook 和 Autograd 都可能错乱;规范做法是只重写 forward。


三、为什么要这样设计?

面试可答:__call__ 是框架入口负责通用逻辑和 hook,forward 是子类实现的纯计算;这样 hook 和扩展都集中在入口,子类只写数学。


面试要点


记忆要点

  1. model(x) → Module.__call__(x) → 做 hook 与检查 → self.forward(x)。
  2. 子类只重写 forward;重写 __call__ 容易破坏 hook 与 Autograd。
  3. 设计目的:入口统一处理 hook 与扩展,子类只关心前向计算。
返回模块 返回总览