不同计算器上的矩阵乘法¶
在本例中,我们将展示如何使用BenchmarkTools
工具包研究代码性能,并比较其在 CPU 和 GPU 上的执行情况。
连接到 GPU¶
向用户提供 GPU 资源仍然是 Engee 平台的一项重要功能。GPU 是一种图形显卡,通过在图形协处理器内数以万计的计算核心上运行代码,可以大大提高代码执行的并行性。
使用 GPU 的主要库是CUDA.jl
。让我们安装这个库以及代码性能评估工具包(BenchmarkTools
软件包)。
# Закомментируйте эту строку, если будете устанавливать библиотеки другим образом
Pkg.add( url="https://github.com/JuliaBinaryWrappers/CUDA_Runtime_jll.jl.git" )
Pkg.add( ["CUDA", "cuDNN", "Flux", "BenchmarkTools"] );
Pkg.instantiate()
CPU 上的矩阵乘法¶
让我们看看在普通 CPU 上进行矩阵乘法运算平均需要多长时间。
N = 1_000
A = rand(ComplexF64, (N,N))
B = rand(ComplexF64, (N,N))
using BenchmarkTools
@benchmark A*B
由于@benchmark
命令会多次运行传递给它的操作,以消除 Julia 固有的 "预热 "效应,因此执行该单元格可能需要很长时间。此外,它还能减少代码随机显示最低性能的罕见情况的影响。
在本例中,实验显示大小为 1000 的复数矩阵乘以 1000 平均需要 300 毫秒。
GPU 上的矩阵乘法¶
要在显卡上进行矩阵乘法运算,需要将矩阵传输到显卡上,这有多种方法。例如,命令A |> gpu
,但由于系统中可能没有 GPU,我们将检查计算空间的配置并选择可用的计算器。
传输后,矩阵Matrix
现在是对象CuArray
。它们之间的乘法运算无需额外代码即可完成(得益于乘法运算符重载)。但是,如果不将两个矩阵转移到同一个求值器,我们就不能用矩阵A_gpu
与矩阵B
相乘(否则会出现错误KernelError: kernel returns a value of type Union{}
)。
using CUDA, Flux
if CUDA.functional()
A_gpu = A |> gpu
B_gpu = B |> gpu
@benchmark A_gpu * B_gpu
end
GPU 上的最短运算时间比 CPU 上的最短运算时间少了近 1 万倍(41 微秒对 384 毫秒)。
结论¶
Julia 允许我们将计算移植到 GPU 上,这样,各种应用计算都可以在不重写代码的情况下加速数倍。我们在 CPU 和图形显卡上进行了矩阵乘法运算,结果发现图形显卡运算由随机复数组成的 1000 乘 1000 平方矩阵的速度比 CPU 快数万倍。