2019款MacBook Pro GPU运行TensorFlow操作仅获1倍加速的技术疑问
背景
我想要测试2019款MacBook Pro的GPU运行TensorFlow操作的加速效果。按照建议,我用TensorFlow内置的tf.multiply()函数编写了测试代码,实现张量与常量的乘法运算:
import tensorflow as tf tensor = tf.constant([[1, 2], [3, 4]]) def cpu(): with tf.device('/CPU:0'): tensor_1 = tf.multiply(tensor, 2) return tensor_1 def gpu(): with tf.device('/device:GPU:0'): tensor_1 = tf.multiply(tensor, 2) return tensor_1 # 先各运行一次预热 cpu() gpu() import time n = 10000 start = time.time() for i in range(n): cpu() end = time.time() cpu_time = end - start start = time.time() for i in range(n): gpu() end = time.time() gpu_time = end - start print('GPU相对CPU的加速比: {}x'.format((cpu_time / gpu_time)))
测试结果
我测得的最高加速比仅为1倍左右。
问题
理论上tf.multiply已经针对GPU做了优化,为什么我得不到2-10倍的更高加速比?
系统环境
- macOS Ventura 13.3.1
- 处理器:2.6 GHz 6核Intel Core i7
- 显卡:AMD Radeon Pro 5300M 4GB、Intel UHD Graphics 630 1536MB
- 内存:16GB 2667 MHz DDR4
- tensorflow-macos版本:2.9.0
- tensorflow-metal版本:0.6.0
- Python版本:3.8.16
问题原因分析
你的测试没体现出GPU优势,核心原因在于任务规模太小,以及GPU调度/数据传输的开销抵消了计算加速:
张量尺寸过小
GPU的核心优势是大规模并行计算,你的测试用的是2x2的极小张量,计算本身耗时微乎其微。相比之下,数据在CPU和GPU之间传输(PCIe总线)、GPU操作的调度开销,反而远大于GPU计算的时间。而CPU处理这种小任务时,不需要跨设备传输,直接在缓存里就能完成,自然速度不会比GPU慢。Python循环的额外开销
你用Python循环执行10000次小操作,每次循环都会触发TensorFlow的图调度、设备上下文切换,这些开销在GPU端占比极高。CPU端的调度开销相对GPU来说小很多,进一步拉平了两者的耗时。GPU未被充分利用
AMD Radeon Pro 5300M有大量流处理器,但极小的计算任务根本无法填满这些计算单元,GPU的并行能力完全没发挥出来。而你的6核i7本身处理简单乘法的效率就很高,两者的实际计算耗时差距可以忽略。
优化方案
要测出真实的GPU加速比,你需要调整测试方式:
增大张量规模:把张量改成比如
1000x1000甚至更大的尺寸,让计算量足够大,覆盖掉数据传输和调度的开销。例如:tensor = tf.constant(tf.random.normal((1000, 1000)))用TensorFlow原生操作替代Python循环:把循环逻辑放到TensorFlow图里,避免Python解释器的开销。比如直接对批量数据做运算,而不是循环10000次小操作。
使用
tf.function装饰器:把cpu()和gpu()函数用@tf.function装饰,让TensorFlow把函数编译成优化后的计算图,减少每次调用的调度开销:@tf.function def cpu(): with tf.device('/CPU:0'): return tf.multiply(tensor, 2) @tf.function def gpu(): with tf.device('/device:GPU:0'): return tf.multiply(tensor, 2)确认GPU真的在工作:可以通过
tf.config.list_physical_devices('GPU')确认GPU被正确识别并使用,避免代码实际上还是跑在CPU上。
按这些方法调整后,你应该能看到GPU明显的加速效果。
内容的提问来源于stack exchange,提问作者Deepak Tatyaji Ahire

