OpenCL 第5课:向量相加

OpenCL程序分为两个部份,一部份是内核代码,负责具体算法。另一部份是主程序负责初始化OpenCL和准备数据。主程序加载内核代码,并按照即定方法进行运算。

内核代码可以写在主程序里面,也可以写在另一个文本文件里,有点像DX中的HLSL和OPENGL里的GLSL。哈哈,明白意思就行了。我们用第一种方法,把代码跟源程序分开写。

调用OpenCL大至分7个步骤

1:初始化OpenCL

2:创建上下文设备

3:创建命令队列

4:创建数据缓冲区

5:将数据上传到缓冲区

6:加载编译代码,创建内核调用函数

7:设置参数,执行内核

8:读回计算结果。

下面我们通过一个向量相加的程序来了解OpenCL 。有A,B两个四维向量,相加后值存在C向量里。OpenCL会根据用户提供的维数,将向量分解成多个任务分发给多个CPU计算。

源码分两部份

(一)vecadd.cl核心代码。

?
1
2
3
4
5
6
7
8
__kernel void vecAdd(__global int* A,
        __global int* B,
        __global int* C)
{
    //获取当前工作项所在位置(线程索引号)
    int idx = get_global_id(0);
    C[idx] = A[idx] + B[idx];
}

__kernel 指明这是一个OpenCL内核,__global 说明指针指向的是全局的设备内存空间,其它的就是C语言的函数的语法。kernel必须返回空类型。

 

(二)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
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <CL/cl.h>//包含CL的头文件
using namespace std;
//四维向量
#define elements 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("vecadd.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[1];
    globalWorkSize[0] = elements;
    cl_int err;
    /*
        定义输入变量和输出变量,并设定初值
    */
    int* buf_A = new int[elements];
    int* buf_B = new int[elements];
    int* buf_C = new int[elements];
    size_t datasize = sizeof(int) * elements;
    buf_A[0] = 1;
    buf_A[1] = 2;
    buf_A[2] = 3;
    buf_A[3] = 4;
    buf_B[0] = 5;
    buf_B[1] = 6;
    buf_B[2] = 7;
    buf_B[3] = 8;
    //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_CPU,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_READ_ONLY,
                             datasize,NULL,NULL);
    bufferC = clCreateBuffer(context,
                             CL_MEM_WRITE_ONLY,
                             datasize,NULL,NULL);
    //step 5:将数据上传到缓冲区
    clEnqueueWriteBuffer(cmdQueue,
                         bufferA,CL_FALSE,
                         0,datasize,
                         buf_A,0,
                         NULL,NULL);
    clEnqueueWriteBuffer(cmdQueue,
                         bufferB,CL_FALSE,
                         0,datasize,
                         buf_B,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,"vecAdd",NULL);
    //step 7:设置参数,执行内核
    clSetKernelArg(kernel,0,sizeof(cl_mem),&bufferA);
    clSetKernelArg(kernel,1,sizeof(cl_mem),&bufferB);
    clSetKernelArg(kernel,2,sizeof(cl_mem),&bufferC);
    clEnqueueNDRangeKernel(cmdQueue,kernel,
                           1,NULL,
                           globalWorkSize,
                           NULL,0,NULL,NULL);
    //step 8:取回计算结果
    clEnqueueReadBuffer(cmdQueue,bufferC,CL_TRUE,0,
                        datasize,buf_C,0,NULL,NULL);
    //输出计算结果
    cout<<"["<<buf_A[0]<<","<<buf_A[1]<<","<<buf_A[2]<<","<<buf_A[3]<<"]+["
    <<buf_B[0]<<","<<buf_B[1]<<","<<buf_B[2]<<","<<buf_B[3]<<"]=["
    <<buf_C[0]<<","<<buf_C[1]<<","<<buf_C[2]<<","<<buf_C[3]<<"]"<<endl;
    //释放所有调用和内存
    clReleaseKernel(kernel);
    clReleaseProgram(program);
    clReleaseCommandQueue(cmdQueue);
    clReleaseMemObject(bufferA);
    clReleaseMemObject(bufferB);
    clReleaseMemObject(bufferC);
    clReleaseContext(context);
    delete buf_A;
    delete buf_B;
    delete buf_C;
    delete buf_code;
    return 0;
}

运算结果:

 [1,2,3,4] + [5,6,7,8] = [6,8,10,12]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/447949.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

同名的const 成员函数

如下代码&#xff1a;struct Derived{ void foo(string) { cout<<"ddd foo"<<endl; }; void foo(string) const { cout<<"ddd foo const"<<endl; };}; int _tmain(int argc, TCH…

springboot 中使用 Mybatis 注解 配置 详解

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 传参方式 使用不同的传参方式&#xff1a; 使用Param 之前博文中的项目使用了这种简单的传参方式&#xff1a; Insert("INSERT IN…

mongodb数据库的备份与恢复

先介绍下命令语法&#xff1a; ./mongodump -h 127.0.0.1:10001 -d lietou -o /usr/local/data -h&#xff1a;MongDB所在服务器地址&#xff0c;例如&#xff1a;127.0.0.1&#xff0c;当然也可以指定端口号&#xff1a;127.0.0.1:10001 -d&#xff1a;需要备份的数据库实例…

OpenCL 第6课:矩阵转置

上一节我们写了个一维向量相加的程序。这节我们来看一个44矩阵转置程序。 4X4矩阵我们采用二维数组进行存储&#xff0c;在程序设计上&#xff0c;我们让转置过程分4次转置完成&#xff0c;就是一次转一行。注意这里的OpenCL的工作维数是二维。&#xff08;当然用一维的方式也…

springboot 系列技术教程目录

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、教程目录地址&#xff1a; springboot系列技术教程目录 二、教程内容&#xff1a; springboot2.X系列&#xff1a; springboot整…

OpenCL 第7课:旋转变换(1)

旋转是一个常用的处理功能。图片中所有的点以某一个点为轴&#xff0c;顺时或逆时方向旋转N个角度。我们利用OpenCL就可以对图片中所有的点进行并行转换&#xff0c;大大提高效率。 上两节中&#xff0c;我们编写了CL文件来传递数组的地址&#xff0c;这一节中我们会多加入几个…

WinForms多线程编程之摇奖程序

利用多线程模拟一个电脑摇奖程序&#xff0c;如图所示。在点击【滚动号码】&#xff0c;启动线程&#xff0c;对后台的电话号码进行循环显示&#xff1b;点击【开奖】按钮&#xff0c;关闭线程&#xff0c;此时显示在文本框中的电话号码即为中奖号码 using System;using System…

idea 版本控制忽略文件、文件夹设置

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 setting 中&#xff1a; 或者底部的 设置 忽略某个文件 后面选择框可以去选择 忽略某个文件夹 后面选择框可以去选择 忽略某种文件 后面…

Windows Azure HandBook (1) IaaS相关技术

《Windows Azure Platform 系列文章目录》 1.Microsoft Azure底层是否由System Center和Hyper-V构成? Microsoft Azure虽然支持Hyper-V的VHD直接上传至Azure云端进行管理&#xff0c;但是Azure底层技术是微软自己研发的、独有的技术&#xff0c;且不对外提供。如果客户想构建属…

OpenCL 第8课:旋转变换(2)

上两节课都是对一个数组进行处理。这节我们来个有意思的。同样是旋转。但我们旋转的对象是张&#xff08;&#xff12;&#xff15;&#xff16;*&#xff12;&#xff15;&#xff16;&#xff09;的图片。图片旋转&#xff14;&#xff15;度&#xff0c;旋转后大小还是&…

VUE: 当前页面 引用自定义公用样式 (:style=“样式名“)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 在当前页面&#xff0c;自行定义了几个样式&#xff0c;在不同地方引用。 2. 实现代码。 样式定义&#xff1a; data() {return {i…

免费的api接口

欢迎大家加群讨论&#xff1a;地址&#xff1a;https://www.apiopen.top 为了方便各类开发者&#xff0c;现提供免费开放Api接口&#xff0c;所有接口均无使用限制&#xff0c;返回格式全是JSON&#xff0c;所以基本能满足大家的开发需求&#xff0c;但请各位不要将这些Api接入…

养成这8个好习惯 开车会很安全的

第一&#xff0c;过路口时减速左右看——要养成过口子时&#xff0c;不管有没有红绿灯&#xff0c;也不管自己的行道是绿灯&#xff0c;都要左顾右盼&#xff08;同时要减速&#xff09;的习惯&#xff0c;观察在横道上的车辆情况&#xff0c;确认没有车横冲&#xff0c;才加速…

css background-attachment:fixed 固定背景、不随内容一起滚动

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 兼容性&#xff1a;全兼容&#xff0c;只不过IE滚动时会有一点不流畅。 background-attachment 有 3 个选项&#xff1a;scroll / fix…

Javacript和AngularJS中的Promises

promise是Javascript异步编程很好的解决方案。对于一个异步方法&#xff0c;执行一个回调函数。比如页面调用google地图的api时就使用到了promise。 function success(position){var cords position.coords;console.log(coords.latitude coords.longitude); }function error(…

男人沉默的真实原因

英国社会学家马克经过调查发现&#xff1a;男人每天的说话量&#xff0c;是女人的一半。但男人们也大多用于朋友圈中、工作中&#xff0c;而与爱人的聊天交流&#xff0c;每天可能不足15分钟&#xff0c;用词量不超过10%。 其实&#xff0c;男人有很多缄默的方法&#xff0c;每…

Visual Studio 使用说明文档、VScode 使用手册

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我只是记录下地址&#xff0c;方便自已以后查看&#xff1a; Visual Studio 使用文档 内容如&#xff1a;

JAVA File的创建及相对路径绝对路径

JAVA File的创建及相对路径绝对路径 转载自 http://blog.sina.com.cn/s/blog_9386f17b0100w2vv.htmlFile f new File("D:/test/mytest.txt");//当执行这句话后在内存的栈空间存在一个f的应用&#xff0c;在堆空间里存在一个mytest.txt对象。注意 这个对象只含有文件…

肾有多好人就有多年轻 男女通用的补肾秘方

每天都坚持喝一碗&#xff0c;现在已经连续喝了三个多星期了&#xff0c;以前有好些白发的地方居然没有复发&#xff0c;而且现在一根也没有啊&#xff0c;我真的很开心。不仅白头发不见了&#xff0c;而且皮肤变白皙和光滑了好多&#xff0c;气色也比原来好了!好东西要大家分享…

Object.keys() Object.values()

Object.keys() //返回对象中各个键值对的键(key) Object.values() //返回对象中各个键值对的值(value) var obj { foo: "bar", baz: 42 };Object.keys(obj) // ["foo", "baz"]Object.values(obj) // ["ba…