导入Keras导致Python multiprocessing.Pool异常的问题求助
Keras与multiprocessing.Pool冲突导致挂起的原因及解决办法
问题回顾
你遇到的情况很典型:导入Keras后,multiprocessing.Pool的starmap调用会卡住,仅输出"Starting"就无响应;移除Keras导入则一切正常。你的测试代码如下:
import keras from multiprocessing import Pool def foo(q,y): print("In foo") return q,y def test(a, b): x = [] if __name__ == '__main__': p = Pool(5) print("Starting") x = p.starmap(foo, [[a,2],[b,4]]) print("Finished") p.close() p.join() print(x) if __name__ == '__main__': test(1,3)
为什么会挂起?
核心原因是Keras(尤其是TensorFlow后端)的初始化逻辑和Python多进程的fork机制不兼容:
- 当你导入Keras时,它会自动初始化TensorFlow的会话或执行器,并占用GPU资源(如果有的话)。这些资源和全局状态绑定在主进程上,无法被
fork出来的子进程安全继承。 - Python多进程默认用
fork方式创建子进程,子进程会复制主进程的所有内存状态——包括Keras已经初始化的GPU上下文。但GPU资源是独占的,子进程无法正常使用这些复制过来的上下文,会陷入无限等待,最终导致整个Pool挂起。 - 加上你使用的是Spyder,它的交互式环境本身有特殊的进程状态,会进一步加剧这个冲突。
解决方法
这里有几个经过验证的解决方案,按推荐程度排序:
1. 延迟Keras导入到子进程内部
最稳妥的方式是让主进程不提前导入Keras,只在子进程执行的函数里导入。这样每个子进程都会独立初始化Keras,避免主进程的全局状态干扰:
from multiprocessing import Pool def foo(q,y): # 仅在子进程中导入Keras import keras print("In foo") return q,y def test(a, b): x = [] if __name__ == '__main__': p = Pool(5) print("Starting") x = p.starmap(foo, [[a,2],[b,4]]) print("Finished") p.close() p.join() print(x) if __name__ == '__main__': test(1,3)
2. 使用spawn/forkserver启动方式替代fork
Python多进程支持三种启动模式,spawn和forkserver会创建全新的Python解释器进程,不会继承主进程的全局状态,完美避开Keras的初始化冲突:
import keras from multiprocessing import Pool, get_context def foo(q,y): print("In foo") return q,y def test(a, b): x = [] if __name__ == '__main__': # 使用spawn上下文创建Pool,也可以换成'forkserver' with get_context('spawn').Pool(5) as p: print("Starting") x = p.starmap(foo, [[a,2],[b,4]]) print("Finished") print(x) if __name__ == '__main__': test(1,3)
⚠️ 注意:spawn的开销比fork略大,但兼容性更好,适合和TensorFlow/Keras这类库配合。
3. 强制Keras使用CPU(如果不需要GPU)
如果你不需要GPU加速,可以在导入Keras前设置环境变量,让TensorFlow只使用CPU,这样就不会产生无法复制的GPU上下文:
import os # 禁用GPU,让TensorFlow只使用CPU os.environ['CUDA_VISIBLE_DEVICES'] = '-1' import keras from multiprocessing import Pool # 后续代码和你的测试代码一致
4. 调整Spyder的运行方式
Spyder的交互式环境可能会干扰多进程,你可以:
- 把代码保存为
.py文件,在Anaconda Prompt中直接运行(而不是在Spyder的控制台里执行); - 在Spyder的设置中,开启"Run in dedicated console"选项,让代码在独立的控制台中运行。
内容的提问来源于stack exchange,提问作者Tristhal
相关产品推荐
相关产品推荐

