MKL学习——基本操作C++实现

前言

前面介绍了各种向量-向量,矩阵-向量,矩阵-矩阵的函数简介。根据自身目前状况,主要使用实数域的操作,也就是说关注单精度float类型的s和双精度double类型的d。还有就是用的基本都是全矩阵,没有经过压缩,也不是对称、三角、带状的某一种情况。所以主要还是总结一般的乘法、加法操作。

【注】代码都以单精度float的情况书写,主要流程要记住,使用mkl_malloc申请内存,使用mkl_free释放内存。n年没用过C++了,凑合看看吧。

学MKL的肯定对编程有一定程度了解,智能提示是一个很好的工具,在VS中,输入cblas_s以后,会自动补全所有的单精度操作函数,那么根据常规经验,就能判断出它到底用于做什么以及需要的参数;比如提示axpby意思就是a*xb*y。还有就是函数有两种,一种是有返回值,一种无返回值,怎么办,只能提示看函数的声明是void还是float或者是double类型即可。

向量-向量

加法

运算

y=ax+by

代码


#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*B
    cblas_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;
}

结果

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");
    //乘法:对应元素乘积的加和
    res=cblas_sdot(n, A, 1, B, 1);
    printf("点乘结果: %2.0f",res);
    printf("\n");
    mkl_free(A);
    mkl_free(B);
    getchar();
    return 0;
}

结果:

The 1st vector is  0 1 2 3 4
The 2st vector is  1 2 3 4 5
点乘结果: 40

二范数

运算:二范数或者欧几里得范数,是所有元素平方和开根号

代码

//计算向量二范数
#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);//计算二范数
    printf("The norm2 of vector is:%2.6f", res);
    mkl_free(A);
    getchar();
}

结果:

The original vector1  2  3  4  5
The norm2 of vector is:7.416198

旋转

运算:将空间中一个点,绕原点旋转的角度

代码:以二维坐标点 (2,0) 绕原点旋转45°为例。代码有点问题,一释放内存就出错,具体原因是对两个向量开辟空间以后又让它们指向了别的地址,造成了开辟空间无用。所以调用Cblas函数,可以直接把指向数组的指针丢进去。暂时先这样理解吧,等把C++复习一遍再来看看分析的对不对。

//旋转,以二维空间中的一个点(2,0)绕原点旋转45°
#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
#include<math.h>
#define M_PI 3.14159265358979323846

int main()
{
    float *A, *B;//A是坐标点,B是旋转矩阵
    float point1[] = { 2 };//旋转点x坐标
    float point2[] = { 0 };//旋转点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");
    //计算旋转后的点
    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;
}

结果:还是比较正确的

The point is ( 2, 0)
The rotated is (1.414214,-1.414214)

缩放

运算

x=ax

代码

//计算向量缩放
#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();
}

结果

The original vector1  2  3  4  5
The scaled vector0.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");
    //交换AB
    cblas_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;
}

结果

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();
}

结果

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

运算:

y:=αAx+βy

代码

//矩阵-向量乘积
#include<stdio.h>
#include<stdlib.h>
#include<mkl.h>
int main()
{
    float *A, *B,*C;//A是矩阵,B是向量,C是向量
    int m = 2;//矩阵行数
    int n = 5;//向量维度,矩阵列数
    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("数组为\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("矩阵-向量乘法结果\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;
}

结果

数组为
 0 1 2 3 4
 5 6 7 8 9
向量为
 1 2 3 4 5
矩阵-向量乘法结果
40 115

乘法2

运算

A:=αxy+A,

代码

//矩阵-向量乘积
#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("数组为\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("向量-向量相乘+矩阵的结果\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;
}

结果

数组为
 1 1 1 1 1
 1 1 1 1 1
向量1为
 1 2
向量2为
 2 3 4 5 6
向量-向量相乘+矩阵的结果
 3  4  5  6  7
 5  7  9 11 13

矩阵-矩阵

乘法1

运算

C:=αop(A)op(B)+βC,

代码

#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(计算时候转置),C维度2*2
    int 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("结果矩阵\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;
}

结果

矩阵1为
 1 2 3
 4 5 6
矩阵2为
 1 1
 1 1
 1 1
矩阵3为
 0 1
 2 3
结果矩阵
 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(计算时候转置),C维度2*2
    int 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("结果矩阵\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;

}

结果

矩阵1为
 1 2 3
 4 5 6
矩阵2为
 1 1 1
 1 1 1
矩阵3为
 0 1
 2 3
结果矩阵
 6 7
1718

注意点

最主要的是记住参数顺序,首先是矩阵 op(A) 和的C行数, op 代表操作,乘法2中的 op 就是转置;然后是矩阵 op(B) C 的列数;随后才是op(A)的列数和 op(B) 的行数。对于乘法2中的第二个矩阵,也就是 B <script type="math/tex" id="MathJax-Element-399">B</script>矩阵,虽然转置了,但是还是以不转置时候,以行存储方式的引导维度,也就是列数为输入参数。
而且丢入函数的参数,并不一定是mkl_malloc开辟的空间,也可以是其它数组,用指针指向数组地址,然后丢到函数就行了。
奉上code(vs2013): MKL -C++基本操作

  • 8
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在Eclipse C中导入第三方mkl库,需要按照以下步骤进行操作: 1. 首先,确保已经在您的系统上安装了Intel Math Kernel Library (MKL)。您可以从Intel官方网站下载并安装MKL。 2. 打开Eclipse C,并创建一个新的C项目,或者打开现有的C项目。 3. 在您的项目中,创建一个文件夹来存放第三方库文件。您可以命名为“lib”或者“third_party”。 4. 将MKL库文件拷贝到刚刚创建的文件夹中。MKL库文件通常包括静态库文件(.lib或.a文件)和动态库文件(.dll或.so文件)。 5. 在Eclipse C中打开您的项目的构建设置。方法是右键单击项目名称,选择“Properties”(或“项目属性”),然后选择“Build Settings”(或“构建设置”)。 6. 在构建设置中,选择“C/C++ Build”(或“C/C++构建”),然后选择“Settings”(或“设置”)选项卡。 7. 在“Settings”选项卡中,选择“Tool Settings”(或“工具设置”),然后选择“GCC Linker”(或“GCC链接器”)。 8. 在“GCC Linker”设置中,选择“Libraries”(或“库”),然后点击“Add”(或“添加”)按钮。 9. 在“Add”对话框中,点击“File System”(或“文件系统”)选项卡,然后选择刚刚创建的库文件文件夹。 10. 选择库文件(静态库文件或动态库文件),点击“OK”按钮。 11. 在构建设置对话框中,点击“Apply”(或“应用”)按钮,然后点击“OK”按钮来保存和关闭对话框。 12. 现在您的项目已经成功导入了第三方MKL库。您可以在代码中使用MKL提供的函数和功能。 请注意,以上步骤可能因为不同的操作系统和Eclipse版本而有所不同,所以请根据您的具体情况进行微调。此外,还需要确保您的项目的编译器和构建设置与MKL库文件的兼容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风翼冰舟

额~~~CSDN还能打赏了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值