从零开始的 Rust 语言 blas 库之预备篇(1)—— blas 基础介绍

下一篇:从零开始的 Rust 语言 blas 库之预备篇(2)—— blas 矩阵格式详解

文章部分参考:https://blog.csdn.net/hehe199807/article/details/108365427

目录索引

  • 从零开始的 Rust 语言 blas 库之预备篇(1)—— blas 基础介绍
    • 前言
    • BLAS 基本说明
      • BLAS 构成
      • BLAS 函数介绍
      • BLAS 主要参数
      • CBLAS 接口与 OpenBLAS
    • roblas 实现计划

前言

最近想着自己即将要踏入深度学习的领域发展,不能够只知其用法却不知道底层。

许多深度学习的模型,底层本质都是矩阵运算,于是突发奇想,打算自己移植一个线性代数库。凭借着之前的并行计算的基础,我选中了 blas 库,也是顺应了时代。

至于开发语言,我选中了 Rust 语言。一部分原因是我曾经参与过 rcore 项目,另一方面是 Rust 语言最近开始被 linux 社区接受了,我想也是时候支持这门新生语言了。

项目取名为 roblas,含义为 rust-only blas,项目地址为:https://github.com/rust-family/roblas

BLAS 基本说明

此处基本参考:https://blog.csdn.net/hehe199807/article/details/108365427

BLAS 库,即 Basic Linear Algrbra Subprograms,是进行向量和矩阵等基本线性代数操作的事实上的数值库。这些程序最早在 1979 年发布,是 LAPACK(Linear Algebra PACKage) 的一部分,便于建立功能更强的数值程序包。BLAS库在高性能计算中被广泛应用,由此衍生出大量优化版本,如 Intel MKL,AMD 的 ACML,ATLAS 等。在 cuda 计算领域,也有实现了相应接口的 cublas 库存在。

BLAS 构成

  • BLAS1:支持向量与向量之间相关的操作。主要是为了编程方便,在实际计算中使用很少,因为不能在大多数机器上实现高性能。
  • BLAS2:支持矩阵与向量之间相关的操作。在 O(n2)O(n^2)O(n2) 时间复杂度实现 O(n2)O(n^2)O(n2) 的浮点运算。在许多向量机上能实现接近峰值的性能。然而在多级存储器的处理器上则性能一般,因为受限于数据在存储器间的迁移。
  • BLAS3:支持矩阵与矩阵之间相关的操作。在 O(n2)O(n^2)O(n2) 时间复杂度实现 O(n3)O(n^3)O(n3) 量级的浮点运算,能充分发挥现代处理器的性能,并且能为用户提供透明的并发机制。

BLAS 函数介绍

BLAS 中对每个函数的功能定义见官方:http://netlib.org/blas/blasqr.pdf。BLAS 函数名中的前缀 “x” 表示参数和返回值的类型:

  • S:单精度实数
  • D:双精度实数
  • C:单精度复数
  • Z:双精度复数
  • Q:混合精度

其中混合精度由 S,D,C,Z 组成,最左边表示返回值类型,其余为参数类型。如 DROTMG 表示的是双精度的平面转换,SSCAL 表示的则是单精度的向量缩放。

BLAS 主要参数

此处有一个解释较好的回答:https://zhuanlan.zhihu.com/p/104287878。

在 BLAS2 和 BLAS3 的函数中,有以下重要的参数:

  • INCX: 向量X的存储步长
  • LDA: 矩阵A的存储步长(主维(Leading Dimension)实际占用的空间)。这个参数查看上述的知乎链接,若无法理解,可以观看老外视频:https://www.youtube.com/watch?v=PhjildK5oO8。在之后的文章中,我也会专门写一篇文章以理解 LDA 这个变量。
  • TRANS: 矩阵的转置形式,T(实数转置)、N(实数非转置)、C(复数共轭转置)、H(复数共轭非转置)
  • UPLO: 对称阵或三角阵的存储方式,U(上三角)、L(下三角)
  • DIAG: 对角线形式,N(非单位对角线)、U(单位对角线)
  • SIDE: 矩阵在操作中的位置,L(左边)、R(右边)

CBLAS 接口与 OpenBLAS

正如之前所说,BLAS 只是一组向量和矩阵运行的接口规范,也可以称为API规范。Netlib 用 fortran 实现了 BLAS 的这些 API 接口,得到的库也叫做 BLAS。Netlib只是一般性地实现了基本功能,并没有对运算做过多的优化。

LAPACK (linear algebra package),是著名的线性代数库,也是 Netlib 用 fortran 语言编写的。其底层是 BLAS,在此基础上定义了很多矩阵和向量高级运算的函数,如矩阵分解、求逆和求奇异值等。该库的运行效率比 BLAS 库高。

从某个角度讲,LAPACK 也可以称作是一组科学计算(矩阵运算)的接口规范。Netlib 实现了这一组规范的功能,得到的这个库叫做 LAPACK 库。

前面 BLAS 和 LAPACK 的实现均是用的 Fortran 语言。为了方便 c 程序的调用,Netlib 开发了 CBLAS 和 CLAPACK。其本质是在 BLAS 和 LAPACK 的基础上,增加了 c 的调用方式。

再有了接口规范之后,其他的组织、个人和公司,就可以根据此规范,实现自己的科学计算库。
开源社区实现的科学计算(矩阵计算)库中,比较著名的两个就是 atlas 和 OpenBLAS。它们都实现了 BLAS 的全部功能,以及 LAPACK 的部分功能,并且他们都对计算过程进行了优化。

下面是一些相关链接:

  • netlib 实现的 blas 库:http://netlib.org/blas/
  • atlas 库:http://www.netlib.org/atlas/
  • lapack 库:http://www.netlib.org/lapack/

roblas 实现计划

目前的计划,是依照 netlib 的 cblas 库进行初版 roblas 的实现,即函数名需要遵守 c 规范,可能考虑后续与 c 进行链接测试。

netlib 中关于 blas 的使用文档非常的粪坑,因此在此找到了两个较好的文档:

https://www.hpc.nec/documents/sdk/SDK_NLC/UsersGuide/blas/f/en/index.html

https://spec.oneapi.com/versions/0.7/elements/oneMKL/source/domains/blas/blas.html#onemkl-blas

平台相关的优化,预计在明年再实现,主要涉及到多线程以及 SIMD 优化。Rust 的多线程支持已经基本完善,x86/x64 的 SIMD 支持也已经到位,理论上可以实现。

码字不易,且看且珍惜~