• MNN--初步学习


    1. 来自阿里
    2. MNN有三个贡献点:
      1. 提出了预推理机制,在线计算推理成本和最优方案
      2. 优化了kernel
      3. 提出后端抽象实现混合调度
    3. MNN的架构:

      1. 分离线和在线两部分。
      2. 离线就是很传统的模型转换、优化、压缩、量化的那一套东西,这里mnn转出的模型文件,后缀是.mnn的。
      3. 设备上的在线推理有三个部分:
        1. 预推理、kernel优化和后端抽象。每个算子在预推理的时候,结合算子信息和后端信息,做成本评估,从方案池里面找一个最优方案出来。然后再对方案做kernel级别的优化,整点SIMD啥的。后端抽象了之后就可以支持各种各样的后端。
        2. 预推理是假设输入大小是固定的,那么计算过程中的内存大小和计算成本都可以预先确定,实现加速。分两个部分:
          1. 计算方案选择、准备-执行的解耦。
          2. 计算方案选择:成本评估机制:C(total)=C(算法)+C(后端)  ,C表示成本。
            1. C(算法):以卷积为例,有滑窗和Winograd两种实现可选,总体思路是根据不同的卷积动态选最小化计算成本的方法:
              1. 如果k=1,那就是个矩阵乘法而已,直接用Strassen算法
              2. 如果k>1就用Winograd将卷积转换成矩阵乘法。
              3. 如果输出大小是1,那就要用滑窗,不然就继续用Winograd了
            2. C(后端):把不同后端的所有算子时间都加起来,然后选时间成本最小的,后端算子的成本计算:
              1. MUL就是乘法次数,FLOPS 和 t_schedule都是后端的确定常量。
          3. 准备-执行的解耦:这个就比较暴力,就是预推理的时候,把网络跑一边,确定下来内存池,真正推理的时候就重用这个内存池,省去频繁的开辟和释放内存。
        3. kernel优化包含两部分,算法优化和调度优化,目标是用复杂度最低的算法,做最高效的调度。作者们主要做了两个:
          1. 一个是Winograd的优化
          2. 另一个是大矩阵乘的优化:就是前面说的那个Strassen算法加速矩阵运算,MNN是第一个用上这个来加速的推理引擎。Strassen是用加法替换乘法,需要递归调用来最大小性能。在MNN中,对于一个矩阵乘[n,k] X [k,m] ->[n,m] ,直接的乘法次数是mnk  ,用Strassen的话只要7*m/2*n/2*k/2  次,但还额外要4次大小为[m/2,k/2]  的矩阵加、4次大小为[n/2,k/2]  的矩阵加、7次大小为 [m/2,n/2]的矩阵加法。所以Strassen算法递归执行的条件是:
            mnk- 7*m/2*n/2*k/2 >4*m/2*k/2+4*n/2*k/2+7*m/2*n/2

    4. 后端抽象类的优点:
      1. 降低复杂度:这个Backend类统一管理资源加载和内存分配,做前端的可以专心搞算子,做后端的可以专心搞后端API
      2. 混合调度:MNN可以灵活组合不同后端的算子混合执行,例如卷积在CPU上跑,ReLU又能放到GPU上跑,就是玩
      3. 轻便:前后端结构,后端可抽离,例如Android不支持Metal就可以直接把Metal模块移除掉,MNN号称支持最全后端
    5. MNN没有局限于逐个算子优化,而是优化了算子更底层的依赖,例如矩阵乘,可以让新算子得到更简单的加速和优化。
  • 相关阅读:
    Java 数据结构与算法 堆
    NVIDIA 安装 CUDA
    Vue3+TS版本Uniapp:项目前置操作
    阿里云服务器经济型e实例租用价格和CPU性能测评
    Jmeter 之 “查看结果树” 界面功能介绍
    大数据有何优缺点
    (实训)C/S架构的考试系统(mysql + socket)
    数据集搜集
    DO280分配持久性存储
    Java的平台无关性
  • 原文地址:https://blog.csdn.net/weixin_45647721/article/details/128060947