TensorFlow不仅提供了CPU版资源调度工具包,而且提供了GPU版资源调度工具包。该工具包在计算中,同时利用CPU和GPU进行数据计算,当处理图像任务时,优势较仅使用CPU处理十分明显,处理速度比单纯使用CPU提高10倍甚至百倍到千倍,极大地提高了开发效率。
GPU版TensorFlow安装后还不能换立即使用,因为需要调用GPU资源,所以需要安装GPU驱动。因为我用的N卡,因此还需要安装NVIDIA驱动CUDA和神经网络加速计算单元cuDNN。
驱动可以直接搜索并到NVIDIA官网进行下载安装,我的电脑配置CPU是i7 9700,显卡是GeForce RTX 2060 SUPER,内存是16G*2,因此这里我都下了最新版CUDA 11.1.0和cuDNN 8.2.0。
CUDA(Compute Unified Device Architecture,统一计算架构),是显卡厂商NVIDIA推出的运算平台。 CUDA™是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。 它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。
NVIDIA cuDNN是用于深度神经网络的GPU加速库。它强调性能、易用性和低内存开销,可以集成到更高级别的机器学习框架中。简单的插入式设计可以让开发人员专注于设计和实现神经网络模型,而不是简单调整性能,同时还可以在GPU上实现高性能现代并行计算。
CUDA看作是一个工作台,上面配有很多工具,如锤子、螺丝刀等。cuDNN是基于CUDA的深度学习GPU加速库,有了它才能在GPU上完成深度学习的计算。它就相当于工作的工具,比如它就是个扳手。但是CUDA这个工作台买来的时候,并没有送扳手。想要在CUDA上运行深度神经网络,就要安装cuDNN,就像你想要拧个螺帽就要把扳手买回来。这样才能使GPU进行深度神经网络的工作,工作速度相较CPU快很多。
nvcc -V
查看CUDA版本来确认是否安装成功,或者输入nvidia-smi
查看显卡驱动版本、cuda版本、显卡使用情况。Result = PASS
即可。C:\ProgramData\NVIDIA GPU Computing Toolkit(✖)
C:\Program Files\NVIDIA GPU Computing Toolkit(✔)
完成后添加环境变量path:
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\lib\x64
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\bin
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\extras\CUPTI\lib64
安装命令:pip install tensorflow-gpu
。自动安装的最新版2.4.0。
安装完进行测试,运行如下代码:
import tensorflow as tf
import timeit # 性能分析模块
# 查看版本
print(tf.__version__)
# CUDA是否可用
print(tf.test.is_built_with_cuda())
# GPU是否可用
print(tf.test.is_gpu_available())
# 创建在cpu环境上运算的两个矩阵
# tf.device:指定模型运行的具体设备
with tf.device('/cpu:0'):
# 用于从“服从指定正态分布的序列”中随机取出指定个数的值
# shape:输出张量的形状,必选
# mean:正态分布的均值,默认为0
# stddev:正态分布的标准差,默认为1.0
# dtype:输出的类型,默认为tf.float32
# seed:随机数种子,是一个整数,当设置之后,每次生成的随机数都一样
# name:操作的名称
cpu_a = tf.random.normal(shape=[10000, 1000])
cpu_b = tf.random.normal([1000, 2000])
print(cpu_a.device, cpu_b.device)
# 创建在gpu环境上运算的两个矩阵
with tf.device('/gpu:0'):
gpu_a = tf.random.normal([10000, 1000])
gpu_b = tf.random.normal([1000, 2000])
print(gpu_a.device, gpu_b.device)
# cpu矩阵相乘
def cpu_run():
with tf.device('/cpu:0'):
# 将矩阵a乘以矩阵b,生成a*b
c = tf.matmul(cpu_a, cpu_b)
return c
# gpu矩阵相乘
def gpu_run():
with tf.device('/gpu:0'):
c = tf.matmul(gpu_a, gpu_b)
return c
# 正式计算前需要热身,避免将初始化时间结算在内
cpu_time = timeit.timeit(cpu_run, number=10)
gpu_time = timeit.timeit(gpu_run, number=10)
print('warm up:', cpu_time, gpu_time)
# 正式计算
cpu_time = timeit.timeit(cpu_run, number=10)
gpu_time = timeit.timeit(gpu_run, number=10)
print('run time:', cpu_time, gpu_time)
timeit的使用可以参考我的另一篇博文:
【timeit】Python小段代码性能测试模块
正确的运行结果如下
2.4.1
True
True
/job:localhost/replica:0/task:0/device:CPU:0 /job:localhost/replica:0/task:0/device:CPU:0
/job:localhost/replica:0/task:0/device:GPU:0 /job:localhost/replica:0/task:0/device:GPU:0
warm up: 0.6571273 1.2346933
run time: 0.6092833999999998 0.001225699999999108
可见GPU运算速度要比CPU快得多。
OK,到此环境部署完成!
Could not load dynamic library 'cusolver64_10.dll'; dlerror: cusolver64_10.dll not found
此时tf.test.is_gpu_available()
返回的结果是False,也无法获取GPU设备,如下:
2.4.1
True
False
/job:localhost/replica:0/task:0/device:CPU:0 /job:localhost/replica:0/task:0/device:CPU:0
/job:localhost/replica:0/task:0/device:CPU:0 /job:localhost/replica:0/task:0/device:CPU:0
warmup: 0.7154982999999997 0.6833096000000003
run time: 0.6948550999999998 0.6916026000000004
解决办法:在C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\bin
路径下,将cusolver64_11.dll文件复制一份并改名为cusolver64_10.dll,再重新运行程序即可顺利解决问题并得到正确的结果。