• 在GPU上运行MATLAB程序


    matlab在运行一些大型程序时会比较慢,如果你的电脑正好有一张不错的显卡,那么为什么不用显卡来加速matlab运行呢?

    本文将讲解如何使用gpu来加速matlab运行程序,并总结适合gpu加速的matlab程序。

    准备工作:电脑上要有显卡,显卡要有cuda core。

    目录

    1. 认识你电脑的GPU

    2. 内存数据搬运

    3. GPU加速举例

    4. GPU加速方法

    5. 适合GPU加速的程序


    1. 认识你电脑的GPU

    MATLAB指令为:gpuDevice

    下面是我电脑上的gpu设备信息

    1. >> gpuDevice
    2. ans =
    3. CUDADevice - 属性:
    4. Name: 'NVIDIA RTX A2000 12GB'
    5. Index: 1
    6. ComputeCapability: '8.6'
    7. SupportsDouble: 1
    8. DriverVersion: 11.5000
    9. ToolkitVersion: 11
    10. MaxThreadsPerBlock: 1024
    11. MaxShmemPerBlock: 49152
    12. MaxThreadBlockSize: [1024 1024 64]
    13. MaxGridSize: [2.1475e+09 65535 65535]
    14. SIMDWidth: 32
    15. TotalMemory: 1.2878e+10
    16. AvailableMemory: 1.1272e+10
    17. MultiprocessorCount: 26
    18. ClockRateKHz: 1200000
    19. ComputeMode: 'Default'
    20. GPUOverlapsTransfers: 1
    21. KernelExecutionTimeout: 1
    22. CanMapHostMemory: 1
    23. DeviceSupported: 1
    24. DeviceAvailable: 1
    25. DeviceSelected: 1

    说明一下打印出来的信息的含义:

    参数含义说明
    Compute Capability计算能力

    NVIDIA GPU Compute Capability解释_Forskamse的博客-CSDN博客

    决定了GPU的通用规格和可用特性。Compute Capability的数值和GPU的计算速度无关,但是和GPU可执行的任务种类有关。

    小数点前的第一位表示设备核心架构,小数点后的一位表示更加细微的进步,包括对核心架构的改进和功能的完善。

    SupportsDouble是否支持双精度浮点运算1表示支持
     MaxThreadsPerBlock每个block中可开的最大线程数量
    MaxShmemPerBlock每个Block可用的最大共享内存大小
    MaxThreadBlockSize三个维度各自最大的线程数量
    MaxGridSize三个维度各自最大的Grid数量
    SIMDWidth同一条指令多个数据位宽同时执行的线程数?
    MultiprocessorCountstreaming multiprocessors 数量
    ComputeMode模式default表示该设备不受限制,多个应用程序可以同时使用它。MATLAB 可以与其他应用程序(包括其他 MATLAB 会话或工作线程)共享设备。
    GPUOverlapsTransfers是否支持覆盖传输
    KernelExecutionTimeout

    长时间运行的内核的超时标志

    CanMapHostMemory支持将主机内存映射到 CUDA 地址空间
    DeviceSupported本机Matlab支持的GPU设备数
    DeviceAvailable指示设备是否可用于当前 MATLAB 会话
    DeviceSelected当前选定设备的标志

     附上一张GPU的架构图,便于理解

    如果你能扫描出类似上面的结果,那么你就可以用gpu加速matlab程序啦。

    2. 内存数据搬运

    在正式开始加速之前,你还得明白一点,那就是数据的搬运。

    如上图所示,正常来讲,matlab运行中的数据都是在内存里的,也就是电脑CPU的内存

    如果要用GPU做计算,首先数据得在GPU的显存上

    这就要研究下数据的搬运了:

    GPU与显存位于显卡上,CPU位于电脑主板上,CPU与GPU之间通过PCIe连接

    虽然PCIe已经是目前最快的接口了,但是毕竟是有速度上限的,所以当数据量多了以后必然传输数据是要时间的,这也是做加速必须要考虑的一个问题:

    加速省下的时间能不能大于数传消耗的时间?

    3. GPU加速举例

    话不多说,直接上代码:

    1. M = single(rand(7000,7000)); % 生成一个随机矩阵
    2. tic
    3. [A1,B1] = eig(M); % 求该随机矩阵的特征值和特征向量
    4. t_cpu = toc
    5. M = gpuArray(M); % 将数据从CPU中搬到GPU
    6. tic
    7. [A2,B2] = eig(M); % 求特征值和特征向量
    8. t_gpu = toc
    9. % A2 = gather(A2); % 将数据从GPU中搬到CPU
    10. % B2 = gather(B2);

    求一个较大矩阵的特征值和特征向量,分别运行在CPU和GPU上,并统计结果

    怎么证明上面这段代码分别跑在了CPU和GPU上呢?很简单,打开任务管理器(win11):

    点击任务管理器的性能标签栏,可以直观的看到CPU和GPU的利用率,CPU和GPU的利用率都依次跑到过100%

    我们看看matlab打印的结果是不是gpu的时间比较短,下面是我电脑运行的结果,大家根据自己的电脑的性能适当的调节矩阵的大小。

    可以看到GPU运行的速度是CPU的1.6倍。

    再看一下matlab的工作区:

    我们发现矩阵A2、B2、M的类型是gpuArray,代码中也调用了gpuArray()函数

    所以GPU加速的关键就在于gpuArray

    4. GPU加速方法

    gpuArray是matlab自带的api函数,下面给出matlab官方的帮助文档:

    Array stored on GPU - MATLAB - MathWorks 中国

    这里总结几个常用的方法:

    方法1:搬运数据  M2 = gpuArray(M1); 

    如第3节所示,讲位于内存的矩阵M1搬移到位于显存的矩阵M2

    方法2:直接声明位于显存的数据  rand(7000,7000,'gpuArray');

    支持这样直接创建gpuArray阵列的函数有300多个,若要查看,输入命令:methods('gpuArray')

    方法3:让函数运行在GPU上  [A2,B2] = arrayfun(@eig,M); 

    arrayfun的加速效果没有前面两个好,gpu没有完全被调起来

    另外与gpu有关的api函数还有一些:

    函数

    功能

    gpuArray

    在GPU上创建阵列。

    gather

    把分布式阵列或gpuArray转移到Matlab的workspace。

    existsOnGPU

    确定gpuArray或CUDAKernel在GPU上可用。

    gpuDevice

    查询或选择GPU设备。

    gpuDeviceCount

    目前GPU的设备数量。

    gputimeit

    在GPU上运行函数所需时间。

    reset

    重置GPU设备并清空它的内存。

    wait(GPUDevice)

    等待GPU计算完成。

    arrayfun

    对GPU阵列上的每个元素应用函数。

    bsxfun

    用于GPU阵列的二元但扩展函数。

    pagefun

    对GPU阵列的每一页应用函数。

    parallel.gpu.CUDAKernel

    从PTX和CU代码创建 GPU CUDA kernel 对象。

    feval

    评估GPU的核。

    setConstantMemory

    设置GPU的一些常量内存。

    mxInitGPU

    这是一个C语言函数,在当前选择的设备上初始化Matlab GPU计算库。

    可自行查阅matlab的帮助文档。

    5. 适合GPU加速的程序

    适合GPU加速的程序具有以下几个特点:

    数据类型不是double。如果把第3节的代码的数据类型改为默认的double,gpu的加速效果就很一般了,我的机器上如果不转化float,cpu反而比gpu还要快(细心的读者可能注意到我任务管理器cpu的主频有4.5GHz,皮)

    高度并行的。各个数据之间运算互不影响,耦合度较低。由于GPU本身硬件基础决定,各个workgroup之间并不相互通信,只有同一workgroup内的work-item之间才相互通信,所以GPU本身并不支持迭代等数据耦合度较高的计算,这是GPU本身要求。

    数据量大的。用大量数据或者用同一数据多次调用同一公式或者计算过程,公式本身并不复杂,只是执行的次数较多。

    接口交互少的。任务可以分为计算密集型和IO密集型。GPU适合计算密集型,即少量的IO读取+大量的计算;而IO密集型,是指多次使用IO读取+少量计算,这种情况涉及到内存与设显存之间的通信问题,主要限制原因是显存带宽问题。

    可多个阶段执行的。运算程序可分解为多个小程序或者同一程序可分多个阶段执行,这就类似于使用集群处理同一任务,将其分解为多个任务碎片分发到各节点执行,以提高运算速率。

  • 相关阅读:
    CentOS中实现基于Docker部署BI数据分析
    Java正常加锁但是没有起作用的问题(纪实)
    Qt+ECharts开发笔记(三):ECharts的柱状图介绍、基础使用和Qt封装Demo
    SpringBoot项目文件上传校验(注解版)
    Redis系列:数据持久化提高可用性
    Nomad 系列-安装
    提升网络质量:UDPspeeder 实现网络优化与提速
    获取阿里云Docker镜像加速器
    基于51单片机温度监控Proteus仿真设计_报警值可调
    聚焦“教-学-评-测-练-管一体化”,推动新型人才培养
  • 原文地址:https://blog.csdn.net/lightninghenry/article/details/123766185