Engee 文档
Notebook

不同计算器上的矩阵乘法

在本例中,我们将展示如何使用BenchmarkTools 工具包研究代码性能,并比较其在 CPU 和 GPU 上的执行情况。

连接到 GPU

向用户提供 GPU 资源仍然是 Engee 平台的一项重要功能。GPU 是一种图形显卡,通过在图形协处理器内数以万计的计算核心上运行代码,可以大大提高代码执行的并行性。

使用 GPU 的主要库是CUDA.jl 。让我们安装这个库以及代码性能评估工具包(BenchmarkTools 软件包)。

In [ ]:
# Закомментируйте эту строку, если будете устанавливать библиотеки другим образом
Pkg.add( url="https://github.com/JuliaBinaryWrappers/CUDA_Runtime_jll.jl.git" )
Pkg.add( ["CUDA", "cuDNN", "Flux", "BenchmarkTools"] );
Pkg.instantiate()

CPU 上的矩阵乘法

让我们看看在普通 CPU 上进行矩阵乘法运算平均需要多长时间。

In [ ]:
N = 1_000

A = rand(ComplexF64, (N,N))
B = rand(ComplexF64, (N,N))

using BenchmarkTools
@benchmark A*B
Out[0]:
BenchmarkTools.Trial: 11 samples with 1 evaluation per sample.
 Range (minmax):  384.014 ms500.289 ms   GC (min … max): 0.00% … 0.00%
 Time  (median):     496.367 ms                GC (median):    0.00%
 Time  (mean ± σ):   462.194 ms ±  50.123 ms   GC (mean ± σ):  0.00% ± 0.00%

            ▁                                                █  
  ▆▁▁▁▁▁▁▁▁▁█▆▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▁█ ▁
  384 ms           Histogram: frequency by time          500 ms <

 Memory estimate: 15.26 MiB, allocs estimate: 2.

由于@benchmark 命令会多次运行传递给它的操作,以消除 Julia 固有的 "预热 "效应,因此执行该单元格可能需要很长时间。此外,它还能减少代码随机显示最低性能的罕见情况的影响。

在本例中,实验显示大小为 1000 的复数矩阵乘以 1000 平均需要 300 毫秒。

GPU 上的矩阵乘法

要在显卡上进行矩阵乘法运算,需要将矩阵传输到显卡上,这有多种方法。例如,命令A |> gpu ,但由于系统中可能没有 GPU,我们将检查计算空间的配置并选择可用的计算器。

传输后,矩阵Matrix 现在是对象CuArray 。它们之间的乘法运算无需额外代码即可完成(得益于乘法运算符重载)。但是,如果不将两个矩阵转移到同一个求值器,我们就不能用矩阵A_gpu 与矩阵B 相乘(否则会出现错误KernelError: kernel returns a value of type Union{} )。

In [ ]:
using CUDA, Flux

if CUDA.functional()
    A_gpu = A |> gpu
    B_gpu = B |> gpu
    @benchmark A_gpu * B_gpu
end
Out[0]:
BenchmarkTools.Trial: 9878 samples with 1 evaluation per sample.
 Range (minmax):   41.620 μs349.520 ms   GC (min … max): 0.00% … 94.80%
 Time  (median):     492.424 μs                GC (median):    0.00%
 Time  (mean ± σ):   503.189 μs ±   3.522 ms   GC (mean ± σ):  6.78% ±  0.98%

                                                            █    
  ▃▂▂▂▂▁▁▁▁▁▂▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▂▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▁▁▂▁▂▂▂▂▂▃█ ▂
  41.6 μs          Histogram: frequency by time          509 μs <

 Memory estimate: 1.62 KiB, allocs estimate: 71.

GPU 上的最短运算时间比 CPU 上的最短运算时间少了近 1 万倍(41 微秒对 384 毫秒)。

结论

Julia 允许我们将计算移植到 GPU 上,这样,各种应用计算都可以在不重写代码的情况下加速数倍。我们在 CPU 和图形显卡上进行了矩阵乘法运算,结果发现图形显卡运算由随机复数组成的 1000 乘 1000 平方矩阵的速度比 CPU 快数万倍。