上一节我们写了个一维向量相加的程序。这节我们来看一个4×4矩阵转置程序。

4X4矩阵我们采用二维数组进行存储,在程序设计上,我们让转置过程分4次转置完成,就是一次转一行。注意这里的OpenCL的工作维数是二维。(当然用一维的方式也可以,只是在CL代码中要用到循环,效率不高)

程序分两部份:

(1)transposition.cl代码

?
1
2
3
4
5
6
7
8
9
10
11
__kernel void transposition(__global int* A,
                    __global int* B)
{
    //获取索引号,这里是二维的,所以可以取两个
    //否则另一个永远是0
    int col = get_global_id(0);
    int row = get_global_id(1);
    B[col*4+row] = A[row*4+col];
}

(2)main.cpp代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <CL/cl.h>//包含CL的头文件
using namespace std;
//4x4数组
#define dim_x 4
#define dim_y 4
//从外部文件获取cl内核代码
bool GetFileData(const char* fname,string& str)
{
    FILE* fp = fopen(fname,"r");
    if(fp==NULL)
    {
        printf("no found file\n");
        return false;
    }
    int n=0;
    while(feof(fp)==0)
    {
        str += fgetc(fp);
    }
    return true;
}
int main()
{
    //先读外部CL核心代码,如果失败则退出。
    //代码存buf_code里面
    string code_file;
    if(false == GetFileData("transposition.cl",code_file))
        return 0;
    char* buf_code = new char[code_file.size()];
    strcpy(buf_code,code_file.c_str());
    buf_code[code_file.size()-1] = NULL;
    //声明CL所需变量。
    cl_device_id device;
    cl_platform_id platform_id = NULL;
    cl_context context;
    cl_command_queue cmdQueue;
    cl_mem bufferA,bufferB,bufferC;
    cl_program program;
    cl_kernel kernel = NULL;
    //我们使用的是二维向量
    //设定向量大小(维数)
    size_t globalWorkSize[2];
    globalWorkSize[0] = dim_x ;
    globalWorkSize[1] = dim_y;
    cl_int err;
    /*
        定义输入变量和输出变量,并设定初值
    */
    int buf_A[dim_x][dim_y];
    int buf_B[dim_x][dim_y];
    size_t datasize = sizeof(int) * dim_x * dim_y;
    int n=0;
    int m=0;
    for(n=0;n<dim_x;n++)
    {
        for(m=0;m<dim_y;m++)
        {
            buf_A[m][n] = m + n*dim_x;
        }
    }
    //step 1:初始化OpenCL
    err = clGetPlatformIDs(1,&platform_id,NULL);
    if(err!=CL_SUCCESS)
    {
        cout<<"clGetPlatformIDs error"<<endl;
        return 0;
    }
    //这次我们只用CPU来进行并行运算,当然你也可以该成GPU
    clGetDeviceIDs(platform_id,CL_DEVICE_TYPE_GPU,1,&device,NULL);
    //step 2:创建上下文
    context = clCreateContext(NULL,1,&device,NULL,NULL,NULL);
    //step 3:创建命令队列
    cmdQueue = clCreateCommandQueue(context,device,0,NULL);
    //step 4:创建数据缓冲区
    bufferA = clCreateBuffer(context,
                             CL_MEM_READ_ONLY,
                             datasize,NULL,NULL);
    bufferB = clCreateBuffer(context,
                             CL_MEM_WRITE_ONLY,
                             datasize,NULL,NULL);
    //step 5:将数据上传到缓冲区
    clEnqueueWriteBuffer(cmdQueue,
                         bufferA,CL_FALSE,
                         0,datasize,
                         buf_A,0,
                         NULL,NULL);
    //step 6:加载编译代码,创建内核调用函数
    program = clCreateProgramWithSource(context,1,
                                        (const char**)&buf_code,
                                        NULL,NULL);
    clBuildProgram(program,1,&device,NULL,NULL,NULL);
    kernel = clCreateKernel(program,"transposition",NULL);
    //step 7:设置参数,执行内核
    clSetKernelArg(kernel,0,sizeof(cl_mem),&bufferA);
    clSetKernelArg(kernel,1,sizeof(cl_mem),&bufferB);
    //<span style="color: #ff0000;"><strong>注意这里第三个参数已经改成2,表示二维数据。</strong></span>
    clEnqueueNDRangeKernel(cmdQueue,kernel,
                           2,NULL,
                           globalWorkSize,
                           NULL,0,NULL,NULL);
    //step 8:取回计算结果
    clEnqueueReadBuffer(cmdQueue,bufferB,CL_TRUE,0,
                        datasize,buf_B,0,NULL,NULL);
    //输出计算结果
    for(n=0;n<dim_x;n++)
    {
        for(m=0;m<dim_y;m++)
        {
            cout<< buf_A[m][n] <<",";
        }
        cout<<endl;
    }
    cout<<endl<<"====transposition===="<<endl<<endl;
    for(n=0;n<dim_x;n++)
    {
        for(m=0;m<dim_y;m++)
        {
            cout<< buf_B[m][n] <<",";
        }
        cout<<endl;
    }
    //释放所有调用和内存
    clReleaseKernel(kernel);
    clReleaseProgram(program);
    clReleaseCommandQueue(cmdQueue);
    clReleaseMemObject(bufferA);
    clReleaseMemObject(bufferB);
    clReleaseContext(context);
    delete buf_code;
    return 0;
}

运算结果:

OpenCL 第6课:矩阵转置相关推荐

  1. 不是方阵有逆矩阵吗_吴恩达机器学习笔记18逆矩阵、矩阵转置

    本文是吴恩达<机器学习>视频笔记第18篇,对应第1周第18个视频. "Linear Algebra review(optional)--Inverse and transpose ...

  2. 矩阵乘以其矩阵转置求导-数学

    20210703 矩阵论 https://zhuanlan.zhihu.com/p/288541909?utm_source=wechat_session 矩阵运算法则 20210529 https: ...

  3. LHC大神问的矩阵转置问题

    数学中线性代数中提到的矩阵转置,其实在我们的业务场景中也有需要的地方,比如LHC大神问到的这个问题 那么如何进行行列转换呢? 代码如下: <?php$array=array('部门1'=> ...

  4. numpy 矩阵转置

    numpy 矩阵转置 import numpy as np a1 = np.arange(0,10).reshape(2,5) print(a1) [[0 1 2 3 4][5 6 7 8 9]] a ...

  5. java 矩阵转置算法

    工作中用到了行列转置,把这两种情况的算法记下来,以便后用 1.行列数相等的转置 1 /** 2 * @description 矩阵转置 3 * @author oldmonk 4 * @time 20 ...

  6. js 矩阵转置_js对象数组矩阵转置(行转列)的实践

    最近项目中有个需求需要将一个类似二维数组的数据矩阵转置(行转列)我通过查资料发现这是很简单的.只需要经过下面的处理就没问题了.但... var newArray = tansDatas[0].map( ...

  7. c语言三元组稀疏矩阵的转置实验报告,稀疏矩阵三元组实现矩阵转置算法实验报告.doc...

    稀疏矩阵三元组实现矩阵转置算法实验报告.doc 1实验三稀疏矩阵的三元组表示实现矩阵转置算法学院专业班学号姓名一.实习目的1掌握稀疏矩阵的三元组顺序表存储表示:2掌握稀疏矩阵三元组表示的传统转置算法的 ...

  8. python【蓝桥杯vip练习题库】ADV-304矩阵转置

    **试题 算法提高 矩阵转置 资源限制 时间限制:1.0s 内存限制:256.0MB [问题描述] 给定一个n×m矩阵相乘,求它的转置.其中1≤n≤20,1≤m≤20,矩阵中的每个元素都在整数类型(4 ...

  9. Boost:矩阵转置的测试程序

    Boost:矩阵转置的测试程序 实现功能 C++实现代码 实现功能 Boost的compute模块,矩阵转置的测试程序 C++实现代码 #include <iostream> #inclu ...

最新文章

  1. python 报错 IndentationError: expected an indented block SyntaxError: invalid character in identifie
  2. java并行任务dispatch_Java模拟 双分派Double Dispatch
  3. 有这么一群人,他们通过AI撬动世界!
  4. 图像篡改检测pytorch版本
  5. docker虚拟机动态扩展内存
  6. Centos 7 搭建.net web项目
  7. leetcode 113. 路径总和 II(Path Sum II)
  8. python 爬取贝壳网小区名称_如何使用 python 爬取全国小区名称
  9. Linux上安装wkhtmltopdf,以及调试所遇到的问题
  10. 您是如何开始使用Linux的?
  11. python命令解析_python学习(命令行的解析)
  12. 如何在本机使用正式版的SAP Business One的Common库的Lisence服务
  13. Nginx日志安全分析脚本
  14. jstl错误:According to TLD or attribute directive in tag file, attribute value does not accept any expr
  15. tomcat容器启动
  16. 帆软报表决策系统自定义登录界面 使用验证码登录 教程一
  17. 盘点App测试会用到哪些工具
  18. Camera2 闪光灯梳理
  19. 方向导数(Directional derivatives)
  20. 7033: Lounge Lizards(lis)

热门文章

  1. 详解Class类文件的结构(下)
  2. REVERSE-COMPETITION-HGAME2022-Week2
  3. C语言实现TEA系列加解密算法
  4. LeetCode 375. 猜数字大小 II
  5. 【HDU - 4055】Number String(dp,思维)
  6. 【ZOJ - 4029】Now Loading!!!(整除分块,思维,二分,前缀和)
  7. 【HDU - 1281 】棋盘游戏 (经典的二分图匹配,匈牙利算法,枚举删除顶点,必须边,关建边)
  8. Coursera自动驾驶课程第10讲:Feedforward Neural Networks
  9. 机器学习笔记(五):逻辑回归
  10. oracle如何把字符集改回默认,更改oracle字符集