MKL学习——基本操作C++实现
前言
前面介紹了各種向量-向量,矩陣-向量,矩陣-矩陣的函數(shù)簡介。根據(jù)自身目前狀況,主要使用實數(shù)域的操作,也就是說關(guān)注單精度float類型的s和雙精度double類型的d。還有就是用的基本都是全矩陣,沒有經(jīng)過壓縮,也不是對稱、三角、帶狀的某一種情況。所以主要還是總結(jié)一般的乘法、加法操作。
【注】代碼都以單精度float的情況書寫,主要流程要記住,使用mkl_malloc申請內(nèi)存,使用mkl_free釋放內(nèi)存。n年沒用過C++了,湊合看看吧。
學(xué)MKL的肯定對編程有一定程度了解,智能提示是一個很好的工具,在VS中,輸入cblas_s以后,會自動補全所有的單精度操作函數(shù),那么根據(jù)常規(guī)經(jīng)驗,就能判斷出它到底用于做什么以及需要的參數(shù);比如提示axpby意思就是a*x加b*y。還有就是函數(shù)有兩種,一種是有返回值,一種無返回值,怎么辦,只能提示看函數(shù)的聲明是void還是float或者是double類型即可。
向量-向量
加法
運算
代碼 #include<stdio.h> #include<stdlib.h> #include<mkl.h> int main() {float *A, *B;//兩個向量int a=1, b=1;//標量int n = 5;//向量大小A = (float *)mkl_malloc(n * 1 * sizeof(float), 64);B = (float *)mkl_malloc(n * 1 * sizeof(float), 64);printf("The 1st vector is ");for (int i = 0; i < n; i++){A[i] = i;printf("%2.0f", A[i]);}printf("\n");printf("The 2st vector is ");for (int i = 0; i < n; i++){B[i] =i+1;printf("%2.0f", B[i]);}printf("\n");//計算a*A+b*Bcblas_saxpby(n, a, A, 1, b, B, 1);printf("The a*A+b*B is ");for (int i = 0; i < n; i++){printf("%2.0f", B[i]);}printf("\n");mkl_free(A);mkl_free(B);getchar();return 0; }
結(jié)果
The 1st vector is 0 1 2 3 4 The 2st vector is 1 2 3 4 5 The a*A+b*B is 1 3 5 7 9乘法
運算:向量點乘
代碼:
//乘法 #include<stdio.h> #include<stdlib.h> #include <mkl.h>int main() {float *A, *B;//兩個向量int a = 1, b = 1;//標量int n = 5;//向量大小float res;A = (float *)mkl_malloc(n * 1 * sizeof(float), 64);B = (float *)mkl_malloc(n * 1 * sizeof(float), 64);printf("The 1st vector is ");for (int i = 0; i < n; i++){A[i] = i;printf("%2.0f", A[i]);}printf("\n");printf("The 2st vector is ");for (int i = 0; i < n; i++){B[i] = i + 1;printf("%2.0f", B[i]);}printf("\n");//乘法:對應(yīng)元素乘積的加和res=cblas_sdot(n, A, 1, B, 1);printf("點乘結(jié)果: %2.0f",res);printf("\n");mkl_free(A);mkl_free(B);getchar();return 0; }結(jié)果:
The 1st vector is 0 1 2 3 4 The 2st vector is 1 2 3 4 5 點乘結(jié)果: 40二范數(shù)
運算:二范數(shù)或者歐幾里得范數(shù),是所有元素平方和開根號
代碼
//計算向量二范數(shù) #include<stdio.h> #include<stdlib.h> #include<mkl.h> void main() {float *A;int n = 5;float res;A = (float *)mkl_malloc(n*sizeof(float), 64);printf("The original vector:\n");for (int i = 0; i < n; i++){A[i] = i + 1;printf("%2.0f ", A[i]);}printf("\n");res = cblas_snrm2(n, A, 1);//計算二范數(shù)printf("The norm2 of vector is:%2.6f", res);mkl_free(A);getchar(); }結(jié)果:
The original vector:1 2 3 4 5 The norm2 of vector is:7.416198旋轉(zhuǎn)
運算:將空間中一個點,繞原點旋轉(zhuǎn)的角度
代碼:以二維坐標點(2,0)繞原點旋轉(zhuǎn)45°為例。代碼有點問題,一釋放內(nèi)存就出錯,具體原因是對兩個向量開辟空間以后又讓它們指向了別的地址,造成了開辟空間無用。所以調(diào)用Cblas函數(shù),可以直接把指向數(shù)組的指針丟進去。暫時先這樣理解吧,等把C++復(fù)習(xí)一遍再來看看分析的對不對。
//旋轉(zhuǎn),以二維空間中的一個點(2,0)繞原點旋轉(zhuǎn)45° #include<stdio.h> #include<stdlib.h> #include<mkl.h> #include<math.h> #define M_PI 3.14159265358979323846int main() {float *A, *B;//A是坐標點,B是旋轉(zhuǎn)矩陣float point1[] = { 2 };//旋轉(zhuǎn)點x坐標float point2[] = { 0 };//旋轉(zhuǎn)點y坐標float rotpoint[] = { cos(45.0*M_PI / 180), sin(45.0*M_PI / 180) };//A = (float *)mkl_malloc(1 * sizeof(float), 64);//B = (float *)mkl_malloc(1 * sizeof(float), 64);A = point1;B = point2;printf("The point is (%2.0f,%2.0f)",point1[0],point2[0]);printf("\n");//計算旋轉(zhuǎn)后的點cblas_srot(1, A, 1, B, 1, rotpoint[0], rotpoint[1]);printf("The rotated is (%2.6f,%2.6f)", A[0], B[0]);printf("\n");//mkl_free(A);//mkl_free(B);getchar();return 0; }結(jié)果:還是比較正確的
The point is ( 2, 0) The rotated is (1.414214,-1.414214)縮放
運算
代碼 //計算向量縮放 #include<stdio.h> #include<stdlib.h> #include<mkl.h> void main() {float *A;int n = 5;float scal=0.1;A = (float *)mkl_malloc(n*sizeof(float), 64);printf("The original vector:\n");for (int i = 0; i < n; i++){A[i] = i + 1;printf("%2.0f ", A[i]);}printf("\n");cblas_sscal(n, scal, A, 1);//縮放printf("The scaled vector:\n");for (int i = 0; i < n; i++){printf("%2.1f ", A[i]);}mkl_free(A);getchar(); }
結(jié)果
The original vector:1 2 3 4 5 The scaled vector: 0.1 0.2 0.3 0.4 0.5交換
運算:交換兩個向量
代碼
//交換 #include<stdio.h> #include<stdlib.h> #include<mkl.h>int main() {float *A, *B;//兩個向量int a = 1, b = 1;//標量int n = 5;//向量大小A = (float *)mkl_malloc(n * 1 * sizeof(float), 64);B = (float *)mkl_malloc(n * 1 * sizeof(float), 64);printf("The 1st vector is ");for (int i = 0; i < n; i++){A[i] = i;printf("%2.0f", A[i]);}printf("\n");printf("The 2st vector is ");for (int i = 0; i < n; i++){B[i] = i + 1;printf("%2.0f", B[i]);}printf("\n");//交換ABcblas_sswap(n, A, 1, B, 1);printf("The 1st swapped vctor is");for (int i = 0; i < n; i++){printf("%2.0f", A[i]);}printf("\n");printf("The 2st swapped vctor is");for (int i = 0; i < n; i++){printf("%2.0f", B[i]);}printf("\n");mkl_free(A);mkl_free(B);getchar();return 0; }結(jié)果
The 1st vector is 0 1 2 3 4 The 2st vector is 1 2 3 4 5 The 1st swapped vctor is 1 2 3 4 5 The 2st swapped vctor is 0 1 2 3 4最值
運算:求最大最小值
代碼
//求最大最小值 #include<stdlib.h> #include<stdio.h> #include<mkl.h> void main() {float *A;//向量int n = 5;//向量大小int max, min;A = (float *)mkl_malloc(n * 1 * sizeof(float), 64);printf("The 1st vector is ");for (int i = 0; i < n; i++){A[i] = i;printf("%2.0f", A[i]);}printf("\n");//計算最值位置max=cblas_isamax(n, A, 1);min = cblas_isamin(n, A, 1);printf("The max value is %2.0f, position is %d\n", A[max], max + 1);printf("The min value is %2.0f, position is %d\n", A[min], min + 1);mkl_free(A);getchar(); }結(jié)果
The 1st vector is 0 1 2 3 4 The max value is 4, position is 5 The min value is 0, position is 1矩陣-向量
乘法1
運算:
代碼 //矩陣-向量乘積 #include<stdio.h> #include<stdlib.h> #include<mkl.h> int main() {float *A, *B,*C;//A是矩陣,B是向量,C是向量int m = 2;//矩陣行數(shù)int n = 5;//向量維度,矩陣列數(shù)int a = 1, b = 1;//縮放因子A = (float *)mkl_malloc(m*n*sizeof(float), 64);B = (float *)mkl_malloc(n*sizeof(float), 64);C = (float *)mkl_malloc(m*sizeof(float), 64);//賦值,按行存儲?printf("數(shù)組為\n");for (int i = 0; i < m*n; i++){if (i%n == 0 && i != 0)printf("\n");A[i] = i;printf("%2.0f",A[i]);} printf("\n");printf("向量為\n");for (int i = 0; i < n; i++){B[i] = i + 1;printf("%2.0f", B[i]);}printf("\n");for (int i = 0; i < m*n; i++)C[i] = 0;//2*5的矩陣與5*1的向量相乘cblas_sgemv(CblasRowMajor, CblasNoTrans, m, n, a, A, n, B, 1, b, C, 1);printf("矩陣-向量乘法結(jié)果\n");for (int i = 0; i < m; i++){printf("%2.0f ", C[i]);}mkl_free(A);mkl_free(B);mkl_free(C);getchar();return 0; }
結(jié)果
數(shù)組為0 1 2 3 45 6 7 8 9 向量為1 2 3 4 5 矩陣-向量乘法結(jié)果 40 115乘法2
運算
代碼 //矩陣-向量乘積 #include<stdio.h> #include<stdlib.h> #include<mkl.h> int main() {float *A, *B, *C;//A是矩陣,B是向量int m=2,n = 5;//B,C向量維度int a = 1;//縮放因子A = (float *)mkl_malloc(m*n*sizeof(float), 64);B = (float *)mkl_malloc(m*sizeof(float), 64);C = (float *)mkl_malloc(n*sizeof(float), 64);//賦值,按行存儲?printf("數(shù)組為\n");for (int i = 0; i < m*n; i++){if (i%n == 0 && i != 0)printf("\n");A[i] = 1;printf("%2.0f", A[i]);}printf("\n");printf("向量1為\n");for (int i = 0; i < m; i++){B[i] = i + 1;printf("%2.0f", B[i]);}printf("\n");printf("向量2為\n");for (int i = 0; i < n; i++){C[i] = i+2;printf("%2.0f", C[i]);}printf("\n");//5*1向量乘以1*5向量,加上5*5矩陣cblas_sger(CblasRowMajor, m, n, a, B, 1, C, 1, A, n);printf("向量-向量相乘+矩陣的結(jié)果\n");for (int i = 0; i < m*n; i++){if (i%n == 0 && i != 0)printf("\n");printf("%2.0f ", A[i]);}mkl_free(A);mkl_free(B);mkl_free(C);getchar();return 0; }
結(jié)果
數(shù)組為1 1 1 1 11 1 1 1 1 向量1為1 2 向量2為2 3 4 5 6 向量-向量相乘+矩陣的結(jié)果3 4 5 6 75 7 9 11 13矩陣-矩陣
乘法1
運算
代碼 #include<stdio.h> #include<stdlib.h> #include<mkl.h> int main() {float *A, *B, *C;int m = 2, n = 3, k = 2;//A維度2*3,B維度2*3(計算時候轉(zhuǎn)置),C維度2*2int a = 1, b = 1;//縮放因子A = (float *)mkl_malloc(m*n*sizeof(float), 64);B = (float *)mkl_malloc(n*k*sizeof(float), 64);C = (float *)mkl_malloc(m*k*sizeof(float), 64);printf("矩陣1為\n");for (int i = 0; i < m*n; i++){if (i != 0 && i%n == 0)printf("\n");A[i] = i + 1;printf("%2.0f", A[i]);}printf("\n");printf("矩陣2為\n");for (int i = 0; i < n*k; i++){if (i != 0 && i%k == 0)printf("\n");B[i] = 1;printf("%2.0f", B[i]);}printf("\n");printf("矩陣3為\n");for (int i = 0; i < m*k; i++){if (i != 0 && i%k == 0)printf("\n");C[i] = i;printf("%2.0f", C[i]);}printf("\n");printf("結(jié)果矩陣\n");cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, k, n, a, A, n, B, k, b, C, k);//注意mkn的順序☆for (int i = 0; i < m*k; i++){if (i != 0 && i%k == 0)printf("\n");printf("%2.0f", C[i]);}printf("\n");mkl_free(A);mkl_free(B);mkl_free(C);getchar();return 0; }
結(jié)果
矩陣1為1 2 34 5 6 矩陣2為1 11 11 1 矩陣3為0 12 3 結(jié)果矩陣6 7 1718乘法2
依舊是上述的功能,此處嘗試一下
#include<stdio.h> #include<stdlib.h> #include<mkl.h> int main() {float *A, *B, *C;int m = 2, n = 3, k = 2;//A維度2*3,B維度2*3(計算時候轉(zhuǎn)置),C維度2*2int a = 1, b = 1;//縮放因子A = (float *)mkl_malloc(m*n*sizeof(float), 64);B = (float *)mkl_malloc(k*n*sizeof(float), 64);C = (float *)mkl_malloc(m*k*sizeof(float), 64);printf("矩陣1為\n");for (int i = 0; i < m*n; i++){if (i != 0 && i%n == 0)printf("\n");A[i] = i + 1;printf("%2.0f", A[i]);}printf("\n");printf("矩陣2為\n");for (int i = 0; i < k*n; i++){if (i != 0 && i%n == 0)printf("\n");B[i] = 1;printf("%2.0f", B[i]);}printf("\n");printf("矩陣3為\n");for (int i = 0; i < m*k; i++){if (i != 0 && i%k == 0)printf("\n");C[i] = i;printf("%2.0f", C[i]);}printf("\n");printf("結(jié)果矩陣\n");cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, k, n, a, A, n, B, n, b, C, k);//注意mkn的順序☆for (int i = 0; i < m*k; i++){if (i != 0 && i%k == 0)printf("\n");printf("%2.0f", C[i]);}printf("\n");mkl_free(A);mkl_free(B);mkl_free(C);getchar();return 0;}結(jié)果
矩陣1為1 2 34 5 6 矩陣2為1 1 11 1 1 矩陣3為0 12 3 結(jié)果矩陣6 7 1718注意點
最主要的是記住參數(shù)順序,首先是矩陣op(A)和的C行數(shù),op代表操作,乘法2中的op就是轉(zhuǎn)置;然后是矩陣op(B)和C的列數(shù);隨后才是op(A)的列數(shù)和op(B)的行數(shù)。對于乘法2中的第二個矩陣,也就是B<script type="math/tex" id="MathJax-Element-399">B</script>矩陣,雖然轉(zhuǎn)置了,但是還是以不轉(zhuǎn)置時候,以行存儲方式的引導(dǎo)維度,也就是列數(shù)為輸入?yún)?shù)。
而且丟入函數(shù)的參數(shù),并不一定是mkl_malloc開辟的空間,也可以是其它數(shù)組,用指針指向數(shù)組地址,然后丟到函數(shù)就行了。
奉上code(vs2013): MKL -C++基本操作
總結(jié)
以上是生活随笔為你收集整理的MKL学习——基本操作C++实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MKL学习——线性代数概念相关
- 下一篇: C++ 命名空间