热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

性能比拼!超详细的TengineGEMM矩阵乘法汇编教程

点击我爱计算机视觉标星,更快获取CVML新技术Tengine是OPENAILAB针对前端智能设备开发的软件开发包,核心部分是一个轻量级,模

点击我爱计算机视觉标星,更快获取CVML新技术


Tengine 是OPEN AI LAB 针对前端智能设备开发的软件开发包,核心部分是一个轻量级,模块化,高性能的AI 推断引擎,并支持用DLA、GPU、xPU作为硬件加速计算资源异构加速。

本文为Open AI Lab 工作人员投稿,对深度学习的核心操作GEMM进行了详细的使用介绍,欢迎对模型部署AI推断感兴趣的朋友关注Tengine。

https://github.com/OAID/Tengine

很多刚入门Tengine的开发者想研读Tengine汇编代码,却苦于没有好的汇编入门教程,没有大神带入门,自己看又看不懂,怎么办?福利来了,Tengine带来了一份超详细的gemm汇编教程。

GEMM简介

什么是GEMM? 它的英文全称是 GEneral Matrix to Matrix Multiplication (通用矩阵的矩阵乘法),Gemm在神经网络的计算中占据很重要的位置。Why gemm is at the heart of deep learning[1]介绍了为什么GEMM在深度学习计算中如此重要,以及卷积计算中是如何使用GEMM。

教程大纲

教程分为三部分:

Step1: 纯C实现的gemm

Step2: 调用OpenBLAS的gemm

Step3: Tengine中的gemm

运行这个教程的代码,你需要:

可以执行armv8汇编的环境,比如RK3399

linux操作系统: 本教程的编译脚本使用的是Makefile

 

超简洁的教程源码

Step1: 纯C实现的gemm

step1部分的代码直接执行:

cd step1
make
./test

这个程序中我们计算的矩阵乘法是 A(m,k) * B(k,n) =C(m,n):

矩阵乘法的纯C简洁实现:

void gemm_pure_c(float* A, float* B, float* C,int m,int n,int k)
{for(int i=0;i}

Step2: 调用OpenBLAS的gemm

OpenBLAS[2]是一个开源的基础线性代数计算库,BLAS的英文全称Basic Linear Algebra Subprograms,它在不同的处理器上都做了优化。在Linux上,可以直接通过apt-get安装这个库:

sudo apt-get install libopenblas-dev

运行一下step2的代码

make
export OMP_NUM_THREADS=1
taskset 0x1 ./test

在RK3399上得到的结果是

[m n k]: 256 128 256
[openblas]: 4.68 ms
[pure c]: 32.22 ms
[blas VS pure_C]: maxerr=0.000076

可以看出,调用OpenBLAS库的性能明显优于纯C实现。

Step3:调用Tengine 16x4 kernel的gemm

这部分教程以 Tengine[3]源码中的 sgemm_4x16_interleave.S[4]为例子,对汇编代码做了一些简化,只支持k为4的倍数的情况。

 

在使用Tengine的4x16 kernel之前, 首先要对矩阵A和矩阵B的数据进行interleave。什么是interleave呢?Interleave叫交错排布,表示对数据进行重新排布,为了计算的时候读取数据时能更好地利用缓存。这里我们对矩阵A的数据是对m中的每16个元素进行重排, 对矩阵B的数据是对n的每4个元素进行重排。

 

Tengine的4x16 kernel计算的n=4,m=16的情况,目前支持的k是4的倍数:

我们在汇编代码的loop4中计算k的每四个元素.

  • 加载B的数据到寄存器 v0,v1,v2,v3

  • 加载A的数据到寄存器 v4,v5,v6,v7,v8,v9,v10,v11

ldr q0,[x1] ldr q1, [x1,0x10] ldp q2, q3, [x1,0x20]ldp q4, q5, [x2]ldp q6, q7, [x2,0x20] ldp q8, q9, [x2,0x40]ldp q10,q11,[x2,0x60]

下面的动图演示了4x16的kernel的每条指令是如何进行计算的

最后的汇编对应的是把输出数据保存

stp q16, q17 ,[x0]stp q18, q19 ,[x0, #0x20]stp q20, q21 ,[x0, #0x40]stp q22, q23 ,[x0, #0x60]stp q24, q25 ,[x0, #0x80]stp q26, q27 ,[x0, #0xa0]stp q28, q29 ,[x0, #0xc0]stp q30, q31 ,[x0, #0xe0]

我们在RK3399上执行step3的代码:

cd step3
make
export OMP_NUM_THREADS=1
taskset 0x1 ./test

可以看出, Tengine的4x16 kernel性能在这三种实现中是最优的。

[m n k]: 256 256 256
[tengine 4x16]: 7.71 ms
[openblas]: 9.55 ms
[pure c]: 316.00 ms
[blas VS tengine]: maxerr=0.000061

What's more?

这个教程的代码只是一个示例,part3的代码只支持:

m 是16的倍数

n 是4的倍数

k 是4的倍数

 

看完这个教程,建议可以尝试以下的一些拓展工作:

  • 你可以修改代码来支持任意数值的k,可参考[sgemm_4x16_interleave.S][4]这个汇编代码,添加 loop1.

  • 你可以把 interleave_B4 函数替换成汇编,以优化性能。

  • 你可以拓展代码,支持任意数值的 m and n

  • 你可以尝试写一个 4x4_kernel.S 的armv8汇编

  • 你可以尝试写一个 4x4_kernel.S 的armv7汇编

 

教程源码链接或点击阅读原文获取:

https://github.com/lyuchuny3/Tengine_gemm_tutorial

Reference:

[1] Why gemm is at the heart of deep learning (https://petewarden.com/2015/04/20/why-gemm-is-at-the-heart-of-deep-learning/)

[2]OpenBLAS (https://www.openblas.net/)

[3]Tengine (https://github.com/OAID/Tengine )

[4]sgemm_4x16_interleave.S(https://github.com/OAID/Tengine/blob/master/executor/operator/arm64/conv/sgemm_4x16_interleave.S )


模型压缩与应用部署交流群

关注最新最前沿的神经网络模型压缩、减枝、AI推断技术,扫码添加CV君拉你入群,(如已为CV君其他账号好友请直接私信)

(请务必注明:部署)

喜欢在QQ交流的童鞋,可以加52CV官方QQ群:805388940。

(不会时时在线,如果没能及时通过验证还请见谅)


长按关注我爱计算机视觉



推荐阅读
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • 本文介绍了腾讯最近开源的BERT推理模型TurboTransformers,该模型在推理速度上比PyTorch快1~4倍。TurboTransformers采用了分层设计的思想,通过简化问题和加速开发,实现了快速推理能力。同时,文章还探讨了PyTorch在中间层延迟和深度神经网络中存在的问题,并提出了合并计算的解决方案。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • 建立分类感知器二元模型对样本数据进行分类
    本文介绍了建立分类感知器二元模型对样本数据进行分类的方法。通过建立线性模型,使用最小二乘、Logistic回归等方法进行建模,考虑到可能性的大小等因素。通过极大似然估计求得分类器的参数,使用牛顿-拉菲森迭代方法求解方程组。同时介绍了梯度上升算法和牛顿迭代的收敛速度比较。最后给出了公式法和logistic regression的实现示例。 ... [详细]
  • 【论文】ICLR 2020 九篇满分论文!!!
    点击上方,选择星标或置顶,每天给你送干货!阅读大概需要11分钟跟随小博主,每天进步一丢丢来自:深度学习技术前沿 ... [详细]
  • 3年半巨亏242亿!商汤高估了深度学习,下错了棋?
    转自:新智元三年半研发开支近70亿,累计亏损242亿。AI这门生意好像越来越不好做了。近日,商汤科技已向港交所递交IPO申请。招股书显示& ... [详细]
  • 安装Tensorflow-GPU文档第一步:通过Anaconda安装python从这个链接https:www.anaconda.comdownload#window ... [详细]
  • 2017亚马逊人工智能奖公布:他们的AI有什么不同?
    事实上,在我们周围,“人工智能”让一切都变得更“智能”极具讽刺意味。随着人类与机器智能之间的界限变得模糊,我们的世界正在变成一个机器 ... [详细]
  • 干货 | 携程AI推理性能的自动化优化实践
    作者简介携程度假AI研发团队致力于为携程旅游事业部提供丰富的AI技术产品,其中性能优化组为AI模型提供全方位的优化方案,提升推理性能降低成本࿰ ... [详细]
  • 「爆干7天7夜」入门AI人工智能学习路线一条龙,真的不能再透彻了
    前言应广大粉丝要求,今天迪迦来和大家讲解一下如何去入门人工智能,也算是迪迦对自己学习人工智能这么多年的一个总结吧,本条学习路线并不会那么 ... [详细]
  • Word2vec,Fasttext,Glove,Elmo,Bert,Flairpre-trainWordEmbedding源码数据Github网址:词向量预训练实现Githubf ... [详细]
  • 第2讲 Android Camera Native Framework 初识cameraserver进程
    本讲是AndroidCameraNativeFramework专题的第2讲,我们初识CameraServer,包括如下内容:Camera ... [详细]
  • 每当我尝试使用NEON16位浮点内在函数时都会收到此错误。我没有遇到其他数据类型内在函数的任何问题。是否可以在Android上使用NEON16位浮点内在函数? ... [详细]
  • 操作系统RetHat9.0,存储设备华为3comEX1000在linux上建立能够识别盘阵的方法有三种1、HBA卡;2、TOE卡;3、is ... [详细]
author-avatar
燕子yanzi068_476
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有