BLAS(Basic Linear Algebra Subprograms 基础线性代数程序集)相关算法中文的介绍比较少,所以写一篇简单记录下,难免有误,欢迎拍砖。
BLAS按照功能被分为三个级别:
Level 1:矢量-矢量运算
$y \leftarrow \alpha x + y$
Level 2:矩阵-矢量运算
$y \leftarrow \alpha Ax + \beta y$
Level 3:矩阵-矩阵运算
$C \leftarrow \alpha AB + \beta C$
官方参考实现:http://www.netlib.org/blas/
代码示例选用com.github.fommil.netlib.BLAS(spark官方亦是这个)
本文介绍下Level1
srot
实现数组a,b间数据的处理,处理公式为:
$a_i = c \ast a_i + s \ast b_i$
$b_i = c \ast b_i - s \ast a_i$1
2
3
4
5
6
7public void srot(int n, float[] sx, int _sx_offset, int incx, float[] sy, int _sy_offset, int incy, float c, float s);
参数解析:
n :需要处理的数据总数
sx|sy :互相处理数据的数组
_sx_offset|_sy_offset :sx|sy数组数据处理起始的位置
incx|incy :步长,取数据的间隔
c|s :数据处理的系数
1 | val a = Array(2.0f,3.0f,5.0f,4.0f,1.0f) |
本例中需要处理的数据数量为2,a数组从索引1开始,以步长为1取数据进行处理,也就是取到(3.0,5.0),b数组从索引0开始,以步长为2取数据进行处理,也就是取到(2.0,5.0),那么也就是对这四个数据进行处理,怎么处理呢?
按照公式$a_i = c \ast a_i + s \ast b_i$,$b_i = c \ast b_i - s \ast a_i$
$a_1$ = 3.0 $\ast$ 3+2.0 $\ast$ 2 = 13.0
$a_2$ = 5.0 $\ast$ 3+5.0 $\ast$ 2 = 25.0
$b_0$ = 2.0$\ast$3-3.0$\ast$2 = 0.0
$b_2$ = 5.0$\ast$3-5.0$\ast$2 = 5.0
sscal
实现数组内数据的乘法
$sx_i = sx_i \ast sa$1
2
3
4
5
6public void sscal(int n, float sa, float[] sx, int _sx_offset, int incx);
参数解析:
n :需要处理的数据总数
sx :需要处理数据的数组
_sx_offset :sx数组数据处理起始的位置
incx :步长,取数据的间隔
1 | val a = Array(1.0f,2.0f,3.0f,4.0f,5.0f) |
以步长1从索引0开始取两个数据,也即(1,2),进行乘法,乘法的系数是2.0,所以结果就是(2,4)
saxpy
数组处理,处理公式为:$y=a \ast x+y$1
2
3
4
5
6
7public void saxpy(int n, float sa, float[] sx, int _sx_offset, int incx, float[] sy, int _sy_offset, int incy);
参数解析:
n :需要处理的数据总数
sa :数据处理的系数
sx|sy :互相处理数据的数组
_sx_offset|_sy_offset :sx|sy数组数据处理起始的位置
incx|incy :步长,取数据的间隔
1 | val a = Array(1.0f,2.0f,3.0f,4.0f,5.0f) |
从索引0,以步长1从a取2个数字,也即(1.0,2.0),从索引1,以步长1从b取2个数字,也即(2.0,3.0),执行计算(1.0$\ast$2.0+2.0=4.0,2.0$\ast$2.0+3.0=7.0),放置到刚才b取出数据的位置即为结果
sswap
实现数组内数据的交换1
2
3
4
5
6public void sswap(int n, float[] sx, int _sx_offset, int incx, float[] sy, int _sy_offset, int incy);
参数解析:
n :需要交换的数据总数
sx|sy :互相交换数据的数组
_sx_offset|_sy_offset :sx|sy数组数据交换起始的位置
incx|incy :步长,取数据的间隔
1 | val a = Array(1.0f,3.0f,5.0f,2.0f,4.0f) |
a数组从索引1开始取,步长为1,取俩,也就是(3.0,5.0)
b数组从索引2开始取,步长为2,取俩,也就是(5.0,4.0)
ab取出来的数据互相交换位置即为结果
dasum
实现数组内数据的累加1
2
3
4
5
6public double dasum(int n, double[] dx, int _dx_offset, int incx)
参数解析:
n :表示总共取多少数据累加,取0的话结果为0
dx :执行累加的数据集
_dx_offset :累加第一个数据在数组dx中的index
incx :步长,每次累加的数据的间隔
1 | val d = blas.dasum(2,Array(1.0,2.0,3.0,4.0,5.0),2,2) |
以步长2从索引2开始取2个数据,也即(3.0,5.0),执行加法,结果即8.0。
scopy
实现前一个数组复制到后一个数组中1
2
3
4
5
6public void scopy(int n, float[] sx, int _sx_offset, int incx, float[] sy, int _sy_offset, int incy);
参数解析:
n :需要复制的数据总数
sx|sy :sx为源数据,复制到sy
_sx_offset|_sy_offset :sx|sy数组数据复制|插入的起始的位置
incx|incy :步长,取数据的间隔
1 | val a = Array(1.0f,2.0f,3.0f,4.0f,5.0f) |
从索引0,以步长1从a取2个数字,也即(1.0,2.0),放到b的从索引2开始,步长2的位置,原数据是(3.0,5.0),替换原数据,即得结果。
sdot
矢量的点积
$x = (a_1,a_2,…,a_n)$,$y = (b_1,b_2,…,b_n)$
$sdot(x,y) = a_1 \ast b_1+a_2 \ast b_2+\cdots+a_n \ast b_n$1
2
3
4
5
6public float sdot(int n, float[] sx, int _sx_offset, int incx, float[] sy, int _sy_offset, int incy);
参数解析:
n :需要计算的数据总数
sx|sy :sx|sy为数据源
_sx_offset|_sy_offset :sx|sy数组开始计算的位置
incx|incy :步长,取数据的间隔
1 | val a = Array(1.0f,2.0f,3.0f,4.0f,5.0f) |
从索引2,以步长1从a取2个数字,也即(3.0,4.0),从索引1,以步长1从b取2个数字,也即(2.0,3.0),结果=3.0$\ast$2.0+4.0$\ast$3.0=18.0
sdsdot
同sdot,不过多加一个额外的系数
$x = (a_1,a_2,…,a_n)$,$y = (b_1,b_2,…,b_n)$
$sdot(x,y) = a_1 \ast b_1+a_2 \ast b_2+\cdots+a_n \ast b_n+c$
其中c为系数1
2
3
4
5
6
7public float sdsdot(int n, float sb, float[] sx, int _sx_offset, int incx, float[] sy, int _sy_offset, int incy);
参数解析:
n :需要计算的数据总数
sb :额外需要加的系数
sx|sy :sx|sy为数据源
_sx_offset|_sy_offset :sx|sy数组开始计算的位置
incx|incy :步长,取数据的间隔
1 | val a = Array(1.0f,2.0f,3.0f,4.0f,5.0f) |
从索引1,以步长2从a取2个数字,也即(2.0,4.0),从索引3,以步长1从b取2个数字,也即(4.0,5.0),结果=2.0$\ast$4.0+4.0$\ast$5.0+11.0=39.0
snrm2
欧几里得范数
$x = (a_1,a_2,…,a_n)$
$snrm2(x) = \sqrt{a_1^2+a_2^2+\cdots+a_n^2}$
其中c为系数1
2
3
4
5
6public float snrm2(int n, float[] x, int _x_offset, int incx);
参数解析:
n :需要计算的数据总数
x :x为数据源
_x_offset :x数组开始计算的位置
incx :步长,取数据的间隔
1 | val a = Array(1.0f,2.0f,3.0f,4.0f,5.0f) |
从索引2,以步长1从a取2个数字,也即(3.0,4.0),勾三股四弦五结果=5.0
isamax
求最大值的位置1
2
3
4
5
6public int isamax(int n, float[] sx, int _sx_offset, int incx);
参数解析:
n :需要计算的数据总数
sx :sx为数据源
_x_offset :sx数组开始计算的位置
incx :步长,取数据的间隔
1 | val a = Array(1.0f,2.0f,3.0f,4.0f,5.0f) |
从索引0开始以步长1取出4个数,也即(1.0f,2.0f,3.0f,4.0f),计算最大值的位置(从1开始)