TensorFlow-GPU预测速度慢于TensorFlow-CPU的问题求助
问题分析与解决方案
你的硬件配置(GTX 1080Ti + i7-7700K)理论上GPU推理应该更有优势,但出现反直觉的结果,主要是以下几个核心原因:
1. GPU初始化与模型加载的额外开销
你的计时代码从start=time.time()开始,随后才创建tf.Session——这意味着GPU的初始化(包括CUDA上下文创建、模型图加载到GPU显存)的时间都被算进了总耗时里。而CPU版本的Session初始化和模型加载开销要小得多,这部分差异直接拉低了GPU版本的整体速度。
2. 轻量模型的GPU并行优势未发挥
MobileNet_v1是为移动设备设计的轻量级模型,单张图片的推理计算量并不大。GPU的优势在于大规模并行计算,对于小计算量任务,数据在CPU和GPU之间的传输开销(把图片tensor传到GPU、把推理结果传回CPU)可能会超过GPU本身的计算加速收益。而你的i7-7700K是高性能桌面CPU,单线程处理轻量任务的效率很高,甚至可能比GPU更快。
3. 单样本重复推理而非批量推理
你现在是对同一张图片重复调用9次predict,但每次都是单样本输入。GPU擅长批量处理多个样本的并行计算,单样本的话,GPU的大量核心无法被充分利用,而CPU的多线程(或单线程)处理单样本的开销更低。
针对性解决方案
1. 分离初始化与推理的计时
把Session创建和模型准备的代码放在计时之外,只统计纯推理的时间,同时加入预热推理消除第一次编译开销:
# 先完成初始化和模型加载 with tf.Session(graph=graph) as sess: # 预热推理:消除第一次算子编译的额外开销 predict('/home/4_bikes/test_images/bikerider4.jpg', sess) # 开始计时纯推理过程 start=time.time() for _ in range(9): predict('/home/4_bikes/test_images/bikerider4.jpg',sess) stop=time.time() print('Time taken for prediction :: {}'.format(stop-start))
2. 改用批量推理
把9张图片打包成一个batch输入,让GPU并行处理,充分发挥其核心优势:
# 构造批量输入tensor batch_t = [] img_path = '/home/4_bikes/test_images/bikerider4.jpg' for _ in range(9): t = read_tensor_from_image_file( img_path, input_height=input_height, input_width=input_width, input_mean=input_mean, input_std=input_std) batch_t.append(t) batch_t = np.concatenate(batch_t, axis=0) # 单次批量推理 with tf.Session(graph=graph) as sess: # 预热 sess.run(output_operation.outputs[0], {input_operation.outputs[0]: batch_t[:1]}) start=time.time() results = sess.run(output_operation.outputs[0], {input_operation.outputs[0]: batch_t}) stop=time.time() print('Time taken for batch prediction :: {}'.format(stop-start))
3. 优化GPU设置与版本检查
- 确认Python2环境中的tensorflow-gpu版本与CUDA、cuDNN版本匹配(旧版本TF对GTX1080Ti的优化可能不足);
- 开启GPU显存动态分配,避免初始化时的显存预分配开销:
config = tf.ConfigProto() config.gpu_options.allow_growth = True with tf.Session(graph=graph, config=config) as sess: # 推理代码
- 检查CPU版本是否启用了MKL优化(新版本TF-CPU默认会启用MKL,对Intel CPU的加速很明显),同时确保GPU版本开启了相应的优化选项。
4. 拆分步骤定位瓶颈
你可以在predict函数中给每个步骤单独计时,明确是数据传输、推理还是后续处理拖慢了速度:
def predict(file_name,sess): start_read = time.time() t = read_tensor_from_image_file( file_name, input_height=input_height, input_width=input_width, input_mean=input_mean, input_std=input_std) print(f"Image to tensor time: {time.time()-start_read:.4f}s") start_infer = time.time() results = sess.run(output_operation.outputs[0], {input_operation.outputs[0]: t}) print(f"Inference + data transfer time: {time.time()-start_infer:.4f}s") start_post = time.time() results = np.squeeze(results) index=results.argmax() prediction=labels[index] bike_predictor = bike_classifier() if prediction == 'bikes': bike_predictor.predict(t) else: print('Predicted as :: unknown') print(f"Post-processing time: {time.time()-start_post:.4f}s")
内容的提问来源于stack exchange,提问作者Pratik Kumar




