PyTorch 高配CPU跑深度学习反而更慢(线程爆炸)
在Pytorch中,默认的算子内并行线程数(torch.set_num_threads)是根据系统的物理核心数而非超线程后的逻辑核心数来设置的。例如64个物理核心的CPU,PyTorch默认的算子内并行线程数就是64。
现象
同一个数据集、同一个算法在除了CPU物理核心数之外无差异的两台机器上训练或者推理时,64核机器比4核机器要慢了十倍以上。
| 4核 | 64核 | |
|---|---|---|
| 训练耗时 | 150s | 3600s |
问题原因
“高配CPU跑深度学习反而更慢”,这种现象在行业内被称为“超额订阅或线程爆炸”。
在核心数很多的处理器(如64核、128核的服务器级的CPU)上,如果不对PyTorch线程进行手动限制,主要会因为以下两个致命原因导致性能暴跌:
- 线程上下文切换开销(Context Switching )
当PyTorch 默认启动64或128个线程去处理一个矩阵运算时,操作系统需要不断地在这些线程之间切换,分配CPU时间片。
结果:CPU的大量算力并没有用来算模型,而是全部浪费在了“管理和切换这些线程”的内部消耗上。核心越多,这种所谓的内耗就呈指数级上升。
- 内存带宽与缓存瓶颈(Cache Thrashing )
深度学习是极其消耗内存带宽的。当几百个线程同时试图从CPU的三级缓存(L3 Cache)或系统内存中读取权重和张量时,会导致严重的内存通道拥堵。
结果:线程都在“排队”等待数据跑,CPU核心大部分时间在原地“踏步”(CPU Stalling),导致实际计算效率反而不如只有4核或8核的普通处理器。
特别要注意,如果是部署在k8s上的服务,即使在deployment限制了CPU数为4核心,在Pod里面获取到的CPU数量仍然是节点主机的CPU数量64核。
解决方法
importtorch torch.set_num_threads(2)torch.set_num_interop_threads(1)注意:在导入torch之后立即进行设置,否则后续设置可能会不生效。