MKL学习——向量操作
前言
推薦兩個比較好的教程:
BLAS (Basic Linear Algebra Subprograms)
LAPACK for Windows
命名規范
BLAS基本線性代數子程序的函數命令都有一定規范,便于記憶
<character> <name> <mod> ()character
定義的是數據類型
| c | 復數域,單精度 |
| d | 實數域,雙精度 |
| z | 復數域,雙精度 |
也可結合起來,比如sc代表實數域和復數域的單精度類型,dz代表實數域和復數域的雙精度類型。
name
針對BLAS level 1,也就是向量與向量間的操作的時候
| rot | 向量旋轉 |
| swap | 向量交換 |
針對BLAS level 2和3的情況,也就是矩陣參數類型
| gb | 一般帶狀矩陣 |
| sy | 對稱矩陣 |
| sp | 對稱矩陣(壓縮存儲) |
| sb | 對稱帶狀矩陣 |
| he | 埃爾米特矩陣 Hermitian matrix |
| hp | 埃爾米特矩陣(壓縮存儲) |
| hb | 埃爾米特帶狀矩陣 |
| tr | 三角矩陣 |
| tp | 三角矩陣(壓縮存儲) |
| tb | 三角帶狀矩陣 |
mod
提供操作的額外信息,三種Level情況
針對Level 1
| u | 非共軛向量 |
| g | Givens 旋轉結構 |
| m | 修正 Givens 旋轉 |
| mg | 修正 Givens 旋轉結構 |
針對Level 2
| sv | 求解具有一個未知向量的線性方程組 |
| r | 矩陣的一階更新 |
| r2 | 矩陣的二階更新 |
針對Level 3
| sm | 求解具有多個未知向量的線性方程組 |
| rk | 矩陣的k階更新 |
| r2k | 矩陣的2k階更新 |
函數實例
| cdotc | 復數域,向量-向量點乘,共軛 | |
| scasum | 巨型向量元素和,單精度實數域輸出,單精度復數域輸入 | |
| cdotu | 向量-向量點乘,一般矩陣,單精度 | |
| sgemv | 矩陣-向量點乘,一般矩陣,單精度 | |
| ztrmm | 矩陣-矩陣乘法,三角矩陣,雙精度復數域 |
C接口的調用方法
C接口相對于Fortran有一個優勢就是,可以指定是行優先還是列優先。調用方法就是在正常的命令規范前面加個前綴cblas_。對于復數函數?dotc和?dotu還需要加一個后綴_sub,通過指針返回復數結果,作為后一個參數添加進來。
使用CALBAS需要遵循一些規則 :
- 輸入參數需要使用const修飾
- 非復數標量輸入參數直接使用值傳遞
- 復數標量參數使用void指針傳遞
- 矩陣參數使用地址傳遞
- BLAS類型參數使用合適的枚舉類型代替
- Level 2和3中有一個CLABS_LAYOUT類型的額外參數,作為第一個輸入參數。這個參數指定二維數組是行優先CblasRowMajor還是列優先CblasColMajor
定義的枚舉類型:
enum CBLAS_LAYOUT { CblasRowMajor=101, /* row-major arrays */ CblasColMajor=102}; /* column-major arrays */ enum CBLAS_TRANSPOSE { CblasNoTrans=111, /* trans='N' */ CblasTrans=112, /* trans='T' */ CblasConjTrans=113}; /* trans='C' */ enum CBLAS_UPLO { CblasUpper=121, /* uplo ='U' */ CblasLower=122}; /* uplo ='L' */ enum CBLAS_DIAG { CblasNonUnit=131, /* diag ='N' */ CblasUnit=132}; /* diag ='U' */ enum CBLAS_SIDE { CblasLeft=141, /* side ='L' */ CblasRight=142}; /* side ='R' */矩陣存儲方案
三種存儲方案:
- 全部存儲:比如將矩陣A存儲到二維數組a中,矩陣元素Aij以列優先的方式存儲到a[i+j?lda]中,或者以行優先的形式存儲到a[j+i?lda]中。這里的lda就是數組的引導維度。
- 壓縮存儲:用于存儲對稱陣,埃爾米特矩陣,三角矩陣。對于列優先的布局,上三角和下三角按照列存儲到一個一維數組;或者按照行優先的布局,上三角和下三角按行存儲到一個一維數組中。
- 帶狀存儲:帶狀矩陣被壓縮存儲到一個二維數組中。對于列優先布局,矩陣的列被存儲到對應的數組列中,矩陣對角部分被存儲到數組的特殊行中。對于行優先的布局,矩陣的行被存儲到對應數組的行中,矩陣對角部分被存儲到數組的指定行中。
行優先與列優先
Fortran中以列優先的方式存儲二維數組;在C中,需要數組為行優先的格式,這是C的約定。講道理的話,這句話應該是這樣寫,但是官方文檔給出的英文是
The BLAS routines follow the Fortran convention of storing two-dimensional arrays using column-major layout. When calling BLAS routines from C, remember that they require arrays to be in column-major format, not the row-major format that is the convention for C. Unless otherwise specified, the psuedo-code examples for the BLAS routines illustrate matrices stored using column-major layout.
這里卻寫著是按照列存儲的。但是在Intel? Math Kernel Library Getting Started Tutorial: Using the Intel? Math Kernel Library for Matrix Multiplication中的實例卻是這樣
代碼是
這個for循環明顯是將一行一行的賦值,說明連續存儲的單元是行中相鄰的元素。但是后面的英文又是
The one-dimensional arrays in the exercises store the matrices by placing the elements of each column in successive cells of the arrays.
意思是聯系中的以為數組是將每行列的元素放入到數組單元中。代碼明明是每行的元素放入到其中。這到底是按行存儲還是按列存儲?兩篇參考博客介紹行列存儲的區別: 行優先和列優先的問題,矩陣存儲的兩種方式——行優先與列優先。個人感覺,姑且認為是按行存儲的吧,畢竟代碼是這樣寫的,雖然與文字不一致。如果有同學有何見解,希望在評論區討論討論^_^
Level 1所有函數
所有函數概覽
| cblas_?asum | s, d, sc, dz | 向量和 |
| cblas_?axpy | s, d, c, z | 標量-向量乘積 |
| cblas_?copy | s, d, c, z | 拷貝向量 |
| cblas_?dot | s,d | 點乘 |
| cblas_?sdot | sd,d | 雙精度點乘 |
| cblas_?dotc | c,z | 共軛點乘 |
| cblas_?dotu | c,z | 非共軛點乘 |
| cblas_?nrm2 | s,d,sc,dz | 向量2范數 |
| cblas_?rot | s,d,cs,zd | 繞點旋轉 |
| cblas_?rotg | s,d,c,z | 生成點的Givens旋轉 |
| cblas_?rotm | s,d | 點的修正Givens旋轉 |
| cblas_?rotmg | s,d | 生成點的修正Givens旋轉 |
| cblas_?scal | s, d, c, z, cs, zd | 向量-標量乘法 |
| cblas_?swap | s, d, c, z | 向量-向量交換 |
| cblas_i?amax | s, d, c, z | 絕對值最大元素位置 |
| cblas_i?amin | s, d, c, z | 絕對值最小元素位置 |
| cblas_?cabs1 | s,d | 輔助函數,計算單精度或者雙精度復數的絕對值 |
cblas_?asum
- 作用:計算向量元素和
- 定義函數
運算
計算實數向量的元素和,或者計算復數向量的實部以及虛部的和
res=|Re(x1)|+|Im(x1)|+|Re(x2|+|Im(x2)|+?+|Re(xn)|+|Im(xn)|
輸入參數
n : 向量的元素個數
x : 數組,大小至少是(1+(n?1)?abs(incx))
incx : 指定索引向量x的增量
返回值:向量所有元素的和
cblas_?axpy
- 作用 : 計算向量-標量的積,然后加到結果上
- 定義函數
- 運算
向量與向量之間的操作
y:=a?x+y
輸入參數
n : 指定向量x,y的元素個數
a : 標量a
x : 數組,大小至少是(1+(n?1)?abs(incx))
incx : 指定索引向量x的增量
y : 數組,大小至少是(1+(n?1)?abs(incy))
incy : 指定索引向量y的增量
返回值 : 最終更新得到的向量y
cblas_?copy
作用 : 拷貝一個向量到另一個向量
定義函數
void cblas_scopy (const MKL_INT n, const float *x, const MKL_INT incx, float *y, const MKL_INT incy); void cblas_dcopy (const MKL_INT n, const double *x, const MKL_INT incx, double *y, const MKL_INT incy); void cblas_ccopy (const MKL_INT n, const void *x, const MKL_INT incx, void *y, const MKL_INT incy); void cblas_zcopy (const MKL_INT n, const void *x, const MKL_INT incx, void *y, const MKL_INT incy);運算
拷貝向量 y=x
輸入參數
n : 指定向量x,y的元素個數
x : 數組,大小至少是(1+(n?1)?abs(incx))
incx : 指定索引向量x的增量
y : 數組,大小至少是(1+(n?1)?abs(incy))
incy : 指定索引向量y的增量
返回值 : 當n是正數的時候,向量x的拷貝被返回,否則參數不變。
cblas_?dot
作用 : 計算向量-向量的點乘
定義函數
float cblas_sdot (const MKL_INT n, const float *x, const MKL_INT incx, const float *y, const MKL_INT incy); double cblas_ddot (const MKL_INT n, const double *x, const MKL_INT incx, const double *y, const MKL_INT incy);運算 :
res=∑i=1nxi?yi輸入參數
n,x,incx,y,incy分別代表元素個數,數組x,數組x的索引增量,數組y,數組y的索引增量
返回值 : 返回兩個向量的點乘;如果n<0,返回0
cblas_?sdot
作用 : 計算雙精度向量-向量的點乘
定義函數
float cblas_sdsdot (const MKL_INT n, const float sb, const float *sx, const MKL_INT incx, const float *sy, const MKL_INT incy); double cblas_dsdot (const MKL_INT n, const float *sx, const MKL_INT incx, const float *sy, const MKL_INT incy);運算
?sdot計算的是兩個雙精度向量的內積(點積),中間結果的累積是雙精度的,但是sdsdot返回的結果是單精度的,使用dsdot可以輸出雙精度的結果。其中sdsdot為點積結果加一個標量值sb
輸入參數
n : 輸入向量x和y的維度
sb : 內積的單精度縮放值(僅針對sdsdot)
sx,sy : 數組,包含單精度輸入向量
incx,incy : 兩個數組的索引增量
返回值 : 當n為正的時候,返回兩個數組的點乘(sdsdot結果加一個標量sb);若n≤0,對于sdsdot返回sb,對于dsdot返回0
cblas_?dotc
作用 : 計算一個共軛向量與另一個向量的點積
定義函數
void cblas_cdotc_sub (const MKL_INT n, const void *x, const MKL_INT incx, const void *y, const MKL_INT incy, void *dotc); void cblas_zdotc_sub (const MKL_INT n, const void *x, const MKL_INT incx, const void *y, const MKL_INT incy, void *dotc);運算
res=∑i=1nconjg(xi)?yi
輸入參數
n,x,incx,y,incy分別代表元素個數,數組x及其索引增量,數組y及其增量
輸出 : 如果n>0,輸出共軛向量x與非共軛向量y的點乘,否則返回0
cblas_?dotu
作用 : 計算復數域的向量-向量的點積
定義函數
void cblas_cdotu_sub (const MKL_INT n, const void *x, const MKL_INT incx, const void *y, const MKL_INT incy, void *dotu); void cblas_zdotu_sub (const MKL_INT n, const void *x, const MKL_INT incx, const void *y, const MKL_INT incy, void *dotu);運算
res=∑i=1nxi?yi
其中xi和yi分別是復數向量x和y的元素輸入參數 : 同上
輸出參數 : 如果n>0,返回點積,否則返回0
cblas_?nrm2
作用 : 計算一個向量的歐幾里得范數(Euclidean norm)
定義函數
float cblas_snrm2 (const MKL_INT n, const float *x, const MKL_INT incx); double cblas_dnrm2 (const MKL_INT n, const double *x, const MKL_INT incx); float cblas_scnrm2 (const MKL_INT n, const void *x, const MKL_INT incx); double cblas_dznrm2 (const MKL_INT n, const void *x, const MKL_INT incx);運算
res=||x||
輸入參數 : 元素個數,數組,索引增量
返回值 : 向量x的歐幾里得范數
cblas_?rot
作用 : 平面上繞點旋轉
定義函數
void cblas_srot (const MKL_INT n, float *x, const MKL_INT incx, float *y, const MKL_INT incy, const float c, const float s); void cblas_drot (const MKL_INT n, double *x, const MKL_INT incx, double *y, const MKL_INT incy, const double c, const double s); void cblas_csrot (const MKL_INT n, void *x, const MKL_INT incx, void *y, const MKL_INT incy, const float c, const float s); void cblas_zdrot (const MKL_INT n, void *x, const MKL_INT incx, void *y, const MKL_INT incy, const double c, const double s);運算
通俗寫法
xi=c?xi+s?yiyi=c?yi?s?xi
[xi,yi]=[xi,yi][cs?sc]
官方寫法
輸入參數 : 元素個數,兩個向量,對應的索引增量,c,s表示所繞點的坐標標量
輸出參數 : x的每個元素被c?x+s?y代替,y的每個元素被c?y?s?x代替
cblas_?rotg
作用 : 計算Givens旋轉參數
定義函數
void cblas_srotg (float *a, float *b, float *c, float *s); void cblas_drotg (double *a, double *b, double *c, double *s); void cblas_crotg (void *a, const void *b, float *c, void *s); void cblas_zrotg (void *a, const void *b, double *c, void *s);運算
給定一個點的笛卡爾(Cartesian)坐標(a,b),返回參數c,s,r,z對應Givens旋轉,c,s對應的是酉陣(unitary matrix),類似于
[c?ssc][ab]=[r0]
參數z這樣定義 : 如果|a|>|b|,那么z=s,否則如果c≠0,那么z=1c,否則z=1輸入參數 : a,b分別提供點p的橫x坐標和縱y坐標
輸出參數 : Givens的四個參數
cblas_?rotm
作用 : 修正繞平面是一點的Givens旋轉
定義函數
void cblas_srotm (const MKL_INT n, float *x, const MKL_INT incx, float *y, const MKL_INT incy, const float *param); void cblas_drotm (const MKL_INT n, double *x, const MKL_INT incx, double *y, const MKL_INT incy, const double *param);運算
給定兩個向量x,y,這些向量的每個元素都會被替代為
[xiyi]=H[xiyi]
其中i=1?n,H是修正Givens旋轉矩陣,值存儲在parm[1]至parm[4]中輸入參數
n,x,incx,y,incy,分別表示元素個數,兩個向量,對應增量索引
param : 包含五個參數,param[0]代表切換標志,param[1?4]均包含h11,h12,h21,h22,分別對應數組H的成分,依據標識符,可以得到如下數組H
flag=?1.0:H=[h11h21h12h22]flag=0.0:H=[1.0h21h121.0]flag=1.0:H=[h11?1.01.0h22]flag=?2.0:H=[1.00.00.01.0]
后三種情況,矩陣H中的?0.1,?1.0,0.0可以由標志指定,無需在向量中寫出來輸出 : x的每一個向量被h11?x[i]+h12?y[i]替換,y的每一個向量被h21?x[i]+h22?y[i]替換
cblas_?rotmg
作用 : 計算修正Givens旋轉的參數
定義函數
void cblas_srotmg (float *d1, float *d2, float *x1, const float y1, float *param); void cblas_drotmg (double *d1, double *d2, double *x1, const double y1, double *param);運算
給定輸入向量的笛卡爾坐標(x1,y1),計算將結果向量的y置零時候,計算得到的Givens旋轉矩陣H
[x10]=H[x1d1??√y1d2??√]輸入參數
d1代表向量的x軸縮放因子,d2代表向量的y軸縮放因子,x1,y1是輸入向量的橫縱坐標
輸出
d1是更新矩陣的第一對角元
d2是更新矩陣的第二對角元
x1是縮放之前旋轉向量的x坐標
param同上cblas_?rotmg的輸入parma一樣
cblas_?scal
作用 : 計算向量和標量的乘積
定義函數
void cblas_sscal (const MKL_INT n, const float a, float *x, const MKL_INT incx); void cblas_dscal (const MKL_INT n, const double a, double *x, const MKL_INT incx); void cblas_cscal (const MKL_INT n, const void *a, void *x, const MKL_INT incx); void cblas_zscal (const MKL_INT n, const void *a, void *x, const MKL_INT incx); void cblas_csscal (const MKL_INT n, const float a, void *x, const MKL_INT incx); void cblas_zdscal (const MKL_INT n, const double a, void *x, const MKL_INT incx);運算
x=a?x
輸入參數
n向量的元素個數,a標量,x數組,incx向量x的索引增量
輸出 : 更新后的向量x
cblas_?swap
作用 : 交換向量值
定義函數
void cblas_sswap (const MKL_INT n, float *x, const MKL_INT incx, float *y, const MKL_INT incy); void cblas_dswap (const MKL_INT n, double *x, const MKL_INT incx, double *y, const MKL_INT incy); void cblas_cswap (const MKL_INT n, void *x, const MKL_INT incx, void *y, const MKL_INT incy); void cblas_zswap (const MKL_INT n, void *x, const MKL_INT incx, void *y, const MKL_INT incy);計算:交換向量x和y,互相代替元素值
輸入參數 : 正常的五個輸入,元素個數,數組,增量索引
輸出 : 交換后的向量x,y
cblas_i?amax
作用 : 找到絕對值最大的元素的索引
定義函數
CBLAS_INDEX cblas_isamax (const MKL_INT n, const float *x, const MKL_INT incx); CBLAS_INDEX cblas_idamax (const MKL_INT n, const double *x, const MKL_INT incx); CBLAS_INDEX cblas_icamax (const MKL_INT n, const void *x, const MKL_INT incx); CBLAS_INDEX cblas_izamax (const MKL_INT n, const void *x, const MKL_INT incx);計算 : 給定向量x,函數i?amax返回實數域中絕對值最大的向量元素x[i]的位置,或者返回復數域|Re(x[i])|+|Im(x[i])|和的最大值
如果n非正,則返回
如果向量中有好幾個位置的值等于最大元素,第一個位置將被返回
輸入參數 : n,x,incx分別代表向量元素個數,數組,索引增量
返回值 : 返回最大值元素的位置,比如x[index?1]具有最大的絕對值
cblas_i?amin
作用 : 返回最小值的位置
定義函數
CBLAS_INDEX cblas_isamin (const MKL_INT n, const float *x, const MKL_INT incx); CBLAS_INDEX cblas_idamin (const MKL_INT n, const double *x, const MKL_INT incx); CBLAS_INDEX cblas_icamin (const MKL_INT n, const void *x, const MKL_INT incx); CBLAS_INDEX cblas_izamin (const MKL_INT n, const void *x, const MKL_INT incx);計算 : i?amin返回的是向量的最小絕對值的位置。與i?amax類似
輸入參數: 同i?amax
返回值: 絕對值最小元素位置的索引,比如x[index?1]具有最小的絕對值
cblas_?cabs1
作用: 計算復數的絕對值,是一個輔助函數,用于輔助其它函數的實現
定義函數
float cblas_scabs1 (const void *z); double cblas_dcabs1 (const void *z);計算
res=|Re(z)|+|Im(z)|
輸入: 標量z
返回值: 復數z的絕對值
總結
以上是生活随笔為你收集整理的MKL学习——向量操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Solve
- 下一篇: 【caffe-Windows】识别率批量