RTX2070Super下TensorFlow-GPU性能异常及多进程CUDA报错求助
首先你的GPU利用率只有1%,这说明显卡根本没在满负荷工作,大部分时间都处于闲置状态,这肯定是速度上不去的核心原因。结合你用遗传算法、每个epoch输入相同输出不同的场景,大概率是这几个问题导致的:
模型太小,GPU并行优势无法发挥
RTX2070Super是大显存、高并行的新架构显卡,但如果你的模型规模很小(比如只有几层全连接、参数极少),GPU的多核心并行能力根本用不上。反而因为CPU与GPU之间的数据传输存在开销,加上新架构的单任务延迟可能比老款GTX770更高,最终整体速度反而没优势。你可以试试调大batch_size,或者给模型增加复杂度,看看GPU利用率会不会提升。数据加载/预处理拖了后腿
GPU利用率只有1%,十有八九是CPU在数据预处理或加载环节跟不上——GPU一直在等CPU喂数据,自然闲得发慌。你可以检查下自己的数据管道:是不是还在靠普通Python循环加载数据?赶紧换成tf.data.Dataset,搭配prefetch和map(num_parallel_calls=tf.data.AUTOTUNE)实现异步预处理,让CPU和GPU的工作重叠起来。CUDA/TensorFlow版本适配不当
RTX2070Super属于Turing架构,需要匹配对应的CUDA、cuDNN和TensorFlow版本才能发挥性能。如果你的conda环境里CUDA版本太老(比如低于10.0),TensorFlow无法针对新架构做优化,反而老款GTX770(Kepler架构)在旧版本CUDA下的适配更完善。你可以核对版本要求:TensorFlow-GPU 2.x需要CUDA 10.0+、cuDNN 7.6+,版本不匹配的话建议及时升级。未开启混合精度训练
RTX2070Super支持FP16混合精度训练,能大幅提升计算速度,但该功能默认是关闭的。你可以在代码开头添加tf.keras.mixed_precision.set_global_policy('mixed_float16')开启该功能,而GTX770不支持FP16,这本来就是新显卡的优势,不用白不用。
这个could not synchronize on CUDA context: CUDA_ERROR_NOT_INITIALIZED错误在TensorFlow多进程场景里非常常见,说白了就是CUDA上下文无法跨进程共享。如果父进程提前初始化了TensorFlow(比如创建模型、运行GPU检测),子进程再去初始化CUDA就会产生冲突。解决思路如下:
父进程只负责管理进程,不碰GPU相关操作
把模型创建、训练的代码全部放到子进程中执行,父进程仅负责进程的创建和调度,不要在父进程中调用tf.test.is_gpu_available(),也不要创建任何tf.keras.Model实例。每个子进程独立初始化GPU配置
在每个子进程的代码开头,单独设置GPU内存增长(避免一次性占满显存),再启动TensorFlow相关操作:import tensorflow as tf def train_model(): # 子进程内单独配置GPU gpus = tf.config.list_physical_devices('GPU') if gpus: try: # 动态分配显存,避免一次性占满 for gpu in gpus: tf.config.experimental.set_memory_growth(gpu, True) except RuntimeError as e: print(e) # 在这里构建模型并开始训练 model = build_your_model() model.fit(...)将多进程启动方式改为spawn
Linux下multiprocessing默认使用fork方式,这种方式会继承父进程的CUDA上下文,直接导致冲突。改成spawn方式后,每个子进程都是全新的独立进程,不会继承父进程的GPU状态:import multiprocessing as mp if __name__ == '__main__': mp.set_start_method('spawn') # 创建进程(注意:100个模型同时训练可能显存不足,建议先少量测试) processes = [mp.Process(target=train_model) for _ in range(100)] for p in processes: p.start() for p in processes: p.join()注意显存限制
100个独立模型同时训练,RTX2070Super的8GB显存肯定无法支撑,即使开启内存增长也容易出现显存不足的问题。建议先减少同时训练的模型数量,比如先测试10个,确认没问题后再逐步调整。
内容的提问来源于stack exchange,提问作者Manuel

