PyTorch FOMM模型转TorchScript报collections.deque源码错误求解
TorchScript编译自定义同步类触发源码获取报错的解决方法
报错现象
在给分布式同步逻辑类添加@torch.jit.script注解编译为TorchScript时,触发如下异常:
OSError: Can't get source for <class 'collections.deque'>. TorchScript requires source access in order to carry out compilation, make sure original .py files are available.
报错本质
这个报错并非代码中直接显式引用collections.deque才触发:TorchScript编译器对依赖的标准库对象做类型推导时,会追踪到queue.Queue底层依赖CPython原生实现的collections.deque。这类原生扩展对象没有可被静态解析的Python源码,自然无法完成编译流程。
更核心的问题是,当前需要编译的类本身依赖线程队列、动态函数回调、跨进程消息传递逻辑,从根本上就不符合TorchScript的静态编译规则。就算临时解决了deque的报错,后续还会接连遇到队列锁、Future对象、线程通信相关的同类编译异常。
对应解决方案
- 不对带多线程/跨设备通信逻辑的类添加TorchScript编译注解:这类类的作用是分布式训练时的BatchNorm跨设备同步协调,推理场景下完全不需要依赖这类逻辑,给这类类做Script注解本身就是方向性的错误。
- 导出FOMM推理模型时,直接跳过整套同步BN相关的逻辑:推理流程不需要跨设备参数同步,只需要把同步BN层替换为单设备通用的
nn.BatchNorm2d,移除所有分布式通信类的依赖,仅对核心的前向计算模块(运动估计网络、生成器网络、遮挡预测模块)做TorchScript导出即可。 - 若确实需要在可编译的类中实现队列功能,替换掉不兼容的标准库类:去掉所有带线程锁、跨进程通信能力的队列实现,用TorchScript原生支持的类型(比如通过
torch.jit.annotate(List[Any], [])定义的列表)替代队列的存储功能,同时给所有类成员变量添加明确的类型标注,避免TorchScript自动推导到原生扩展类的类型。 - 移除类中传入的动态回调逻辑:代码中作为成员传入的
master_callback是任意可调用对象,这类动态回调本身就无法被TorchScript静态编译,必须要么把回调的逻辑硬编码到类的内部方法,要么彻底移除回调流程才能走通编译。
常见踩坑提醒
没必要专门去找纯Python实现的deque版本来替换原生deque:就算替换了deque,后续遇到队列内置的条件锁、Future结果传递对象时,还是会触发一模一样的源码获取报错,从根上就不该对这类通信协调类做TorchScript编译。
内容的提问来源于stack exchange,提问作者serg_zhd
相关产品推荐
相关产品推荐

