http://www.cnblogs.com/xudong-bupt/p/3582780.html 

1.OpenCL概念

  OpenCL是一个为异构平台编写程序的框架,此异构平台可由CPU、GPU或其他类型的处理器组成。OpenCL由一门用于编写kernels (在OpenCL设备上运行的函数)的语言(基于C99)和一组用于定义并控制平台的API组成。

  OpenCL提供了两种层面的并行机制:任务并行与数据并行。

2.OpenCL与CUDA的区别

  不同点:OpenCL是通用的异构平台编程语言,为了兼顾不同设备,使用繁琐。

      CUDA是nvidia公司发明的专门在其GPGPU上的编程的框架,使用简单,好入门。

  相同点:都是基于任务并行与数据并行。

3.OpenCL的编程步骤

  (1)Discover and initialize the platforms

    调用两次clGetPlatformIDs函数,第一次获取可用的平台数量,第二次获取一个可用的平台。

  (2)Discover and initialize the devices

    调用两次clGetDeviceIDs函数,第一次获取可用的设备数量,第二次获取一个可用的设备。

  (3)Create  a context(调用clCreateContext函数)

    上下文context可能会管理多个设备device。

  (4)Create a command queue(调用clCreateCommandQueue函数)

    一个设备device对应一个command queue。

    上下文conetxt将命令发送到设备对应的command queue,设备就可以执行命令队列里的命令。

  (5)Create device buffers(调用clCreateBuffer函数)

    Buffer中保存的是数据对象,就是设备执行程序需要的数据保存在其中。

    Buffer由上下文conetxt创建,这样上下文管理的多个设备就会共享Buffer中的数据。

  (6)Write host data to device buffers(调用clEnqueueWriteBuffer函数)

  (7)Create and compile the program

    创建程序对象,程序对象就代表你的程序源文件或者二进制代码数据。

  (8)Create the kernel(调用clCreateKernel函数)

    根据你的程序对象,生成kernel对象,表示设备程序的入口。

  (9)Set the kernel arguments(调用clSetKernelArg函数)

  (10)Configure the work-item structure(设置worksize)

    配置work-item的组织形式(维数,group组成等)

  (11)Enqueue the kernel for execution(调用clEnqueueNDRangeKernel函数)

    将kernel对象,以及 work-item参数放入命令队列中进行执行。

  (12)Read  the output buffer back to the host(调用clEnqueueReadBuffer函数)

  (13)Release OpenCL resources(至此结束整个运行过程)

4.说明

  OpenCL中的核函数必须单列一个文件。

  OpenCL的编程一般步骤就是上面的13步,太长了,以至于要想做个向量加法都是那么困难。

  不过上面的步骤前3步一般是固定的,可以单独写在一个.h/.cpp文件中,其他的一般也不会有什么大的变化。

5.程序实例,向量运算

5.1通用前3个步骤,生成一个文件

  tool.h

  1. #ifndef TOOLH
  2. #define TOOLH
  3.  
  4. #include <CL/cl.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <iostream>
  9. #include <string>
  10. #include <fstream>
  11. using namespace std;
  12.  
  13. /** convert the kernel file into a string */
  14. int convertToString(const char *filename, std::string& s);
  15.  
  16. /**Getting platforms and choose an available one.*/
  17. int getPlatform(cl_platform_id &platform);
  18.  
  19. /**Step 2:Query the platform and choose the first GPU device if has one.*/
  20. cl_device_id *getCl_device_id(cl_platform_id &platform);
  21.  
  22. #endif

  tool.cpp

  1. #include <CL/cl.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <iostream>
  6. #include <string>
  7. #include <fstream>
  8. #include "tool.h"
  9. using namespace std;
  10.  
  11. /** convert the kernel file into a string */
  12. int convertToString(const char *filename, std::string& s)
  13. {
  14. size_t size;
  15. char* str;
  16. std::fstream f(filename, (std::fstream::in | std::fstream::binary));
  17.  
  18. if(f.is_open())
  19. {
  20. size_t fileSize;
  21. f.seekg(, std::fstream::end);
  22. size = fileSize = (size_t)f.tellg();
  23. f.seekg(, std::fstream::beg);
  24. str = new char[size+];
  25. if(!str)
  26. {
  27. f.close();
  28. return ;
  29. }
  30.  
  31. f.read(str, fileSize);
  32. f.close();
  33. str[size] = '\0';
  34. s = str;
  35. delete[] str;
  36. return ;
  37. }
  38. cout<<"Error: failed to open file\n:"<<filename<<endl;
  39. return -;
  40. }
  41.  
  42. /**Getting platforms and choose an available one.*/
  43. int getPlatform(cl_platform_id &platform)
  44. {
  45. platform = NULL;//the chosen platform
  46.  
  47. cl_uint numPlatforms;//the NO. of platforms
  48. cl_int status = clGetPlatformIDs(, NULL, &numPlatforms);
  49. if (status != CL_SUCCESS)
  50. {
  51. cout<<"Error: Getting platforms!"<<endl;
  52. return -;
  53. }
  54.  
  55. /**For clarity, choose the first available platform. */
  56. if(numPlatforms > )
  57. {
  58. cl_platform_id* platforms =
  59. (cl_platform_id* )malloc(numPlatforms* sizeof(cl_platform_id));
  60. status = clGetPlatformIDs(numPlatforms, platforms, NULL);
  61. platform = platforms[];
  62. free(platforms);
  63. }
  64. else
  65. return -;
  66. }
  67.  
  68. /**Step 2:Query the platform and choose the first GPU device if has one.*/
  69. cl_device_id *getCl_device_id(cl_platform_id &platform)
  70. {
  71. cl_uint numDevices = ;
  72. cl_device_id *devices=NULL;
  73. cl_int status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, , NULL, &numDevices);
  74. if (numDevices > ) //GPU available.
  75. {
  76. devices = (cl_device_id*)malloc(numDevices * sizeof(cl_device_id));
  77. status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, numDevices, devices, NULL);
  78. }
  79. return devices;
  80. }

5.2核函数文件

  HelloWorld_Kernel.cl

  1. __kernel void helloworld(__global double* in, __global double* out)
  2. {
  3. int num = get_global_id();
  4. out[num] = in[num] / 2.4 *(in[num]/) ;
  5. }

5.3主函数文件

  HelloWorld.cpp

  1. //For clarity,error checking has been omitted.
  2. #include <CL/cl.h>
  3. #include "tool.h"
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <iostream>
  8. #include <string>
  9. #include <fstream>
  10. using namespace std;
  11.  
  12. int main(int argc, char* argv[])
  13. {
  14. cl_int status;
  15. /**Step 1: Getting platforms and choose an available one(first).*/
  16. cl_platform_id platform;
  17. getPlatform(platform);
  18.  
  19. /**Step 2:Query the platform and choose the first GPU device if has one.*/
  20. cl_device_id *devices=getCl_device_id(platform);
  21.  
  22. /**Step 3: Create context.*/
  23. cl_context context = clCreateContext(NULL,, devices,NULL,NULL,NULL);
  24.  
  25. /**Step 4: Creating command queue associate with the context.*/
  26. cl_command_queue commandQueue = clCreateCommandQueue(context, devices[], , NULL);
  27.  
  28. /**Step 5: Create program object */
  29. const char *filename = "HelloWorld_Kernel.cl";
  30. string sourceStr;
  31. status = convertToString(filename, sourceStr);
  32. const char *source = sourceStr.c_str();
  33. size_t sourceSize[] = {strlen(source)};
  34. cl_program program = clCreateProgramWithSource(context, , &source, sourceSize, NULL);
  35.  
  36. /**Step 6: Build program. */
  37. status=clBuildProgram(program, ,devices,NULL,NULL,NULL);
  38.  
  39. /**Step 7: Initial input,output for the host and create memory objects for the kernel*/
  40. const int NUM=;
  41. double* input = new double[NUM];
  42. for(int i=;i<NUM;i++)
  43. input[i]=i;
  44. double* output = new double[NUM];
  45.  
  46. cl_mem inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, (NUM) * sizeof(double),(void *) input, NULL);
  47. cl_mem outputBuffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY , NUM * sizeof(double), NULL, NULL);
  48.  
  49. /**Step 8: Create kernel object */
  50. cl_kernel kernel = clCreateKernel(program,"helloworld", NULL);
  51.  
  52. /**Step 9: Sets Kernel arguments.*/
  53. status = clSetKernelArg(kernel, , sizeof(cl_mem), (void *)&inputBuffer);
  54. status = clSetKernelArg(kernel, , sizeof(cl_mem), (void *)&outputBuffer);
  55.  
  56. /**Step 10: Running the kernel.*/
  57. size_t global_work_size[] = {NUM};
  58. cl_event enentPoint;
  59. status = clEnqueueNDRangeKernel(commandQueue, kernel, , NULL, global_work_size, NULL, , NULL, &enentPoint);
  60. clWaitForEvents(,&enentPoint); ///wait
  61. clReleaseEvent(enentPoint);
  62.  
  63. /**Step 11: Read the cout put back to host memory.*/
  64. status = clEnqueueReadBuffer(commandQueue, outputBuffer, CL_TRUE, , NUM * sizeof(double), output, , NULL, NULL);
  65. cout<<output[NUM-]<<endl;
  66.  
  67. /**Step 12: Clean the resources.*/
  68. status = clReleaseKernel(kernel);//*Release kernel.
  69. status = clReleaseProgram(program); //Release the program object.
  70. status = clReleaseMemObject(inputBuffer);//Release mem object.
  71. status = clReleaseMemObject(outputBuffer);
  72. status = clReleaseCommandQueue(commandQueue);//Release Command queue.
  73. status = clReleaseContext(context);//Release context.
  74.  
  75. if (output != NULL)
  76. {
  77. free(output);
  78. output = NULL;
  79. }
  80.  
  81. if (devices != NULL)
  82. {
  83. free(devices);
  84. devices = NULL;
  85. }
  86. return ;
  87. }

编译、链接、执行:

  g++ -I /opt/AMDAPP/include/ -o A  *.cpp -lOpenCL ; ./A

  

GPGPU OpenCL编程步骤与简单实例的更多相关文章

  1. Win Socket编程原理及简单实例

    [转]http://www.cnblogs.com/tornadomeet/archive/2012/04/11/2442140.html 使用Linux Socket做了小型的分布式,如Linux ...

  2. Linux C Socket编程原理及简单实例

    部分转自:http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx 1.   什么是TCP/IP.UDP? 2.   Socket在哪里 ...

  3. JNA的步骤、简单实例以及资料整理

    1.步骤 1.编写dll文件,放入项目的bin目录(在window上是dll文件,在Linux上是so文件,dll和so都是由C程序生成)  2.新建接口继承Library  3.加载对应的dll或者 ...

  4. 简单的JDBC编程步骤

    1.加载数据库驱动(com.mysql.jdbc.Driver) 2.创建并获取数据库链接(Connection) 3.创建jdbc statement对象(PreparedStatement) 4. ...

  5. 【并行计算-CUDA开发】GPGPU OpenCL/CUDA 高性能编程的10大注意事项

    GPGPU OpenCL/CUDA 高性能编程的10大注意事项 1.展开循环 如果提前知道了循环的次数,可以进行循环展开,这样省去了循环条件的比较次数.但是同时也不能使得kernel代码太大. 循环展 ...

  6. Win32 API 多线程编程——一个简单实例(含消息参数传递)

    Win32 API进行程序设计具有很多优点:应用程序执行代码小,运行效率高,但是他要求程序员编写的代码较多,且需要管理所有系统提供给程序的资源,要求程序员对Windows系统内核有一定的了解,会占用程 ...

  7. Hibernate(二)__简单实例入门

    首先我们进一步理解什么是对象关系映射模型? 它将对数据库中数据的处理转化为对对象的处理.如下图所示: 入门简单实例: hiberante 可以用在 j2se 项目,也可以用在 j2ee (web项目中 ...

  8. Docker初步认识安装和简单实例

    前话 问题 开发网站需要搭建服务器环境,FQ官网下载软件包,搭建配置nginx,apache,数据库等.官网没有直接可用的运行版本,担心网络流传的非官方发布软件包不安全还得自行编译官方源码安装,忘记步 ...

  9. C++网络套接字编程TCP和UDP实例

    原文地址:C++网络套接字编程TCP和UDP实例作者:xiaojiangjiang 1.       创建一个简单的SOCKET编程流程如下 面向有连接的套接字编程 服务器: 1)  创建套接字(so ...

随机推荐

  1. oracle去掉字段值中的某些字符串

    我想去掉字段值中的“_” select replace(fdisplayname,'_','') from SHENZHENJM1222.B replace 第一个参数:字段/值,第二个参数时替换字符 ...

  2. 洛谷P0248 [NOI2010] 超级钢琴 [RMQ,贪心]

    题目传送门 超级钢琴 题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符 ...

  3. Python类总结-封装(私有属性,方法)

    封装基础 广义上面向对象的封装:代码的保护,面向对象的思想本身就是一种封装 只让自己的对象能调用自己类中的方法 狭义上的封装-面向对象三大特性之一(私有变量,用公有的方法封装私有属性,方法叫封装) 把 ...

  4. iTerm2配置

    1.颜色Solarized 首先下载 Solarized: $ git clone git://github.com/altercation/solarized.git Terminal/iTerm2 ...

  5. java8新特性——并行流与顺序流

    在我们开发过程中,我们都知道想要提高程序效率,我们可以启用多线程去并行处理,而java8中对数据处理也提供了它得并行方法,今天就来简单学习一下java8中得并行流与顺序流. 并行流就是把一个内容分成多 ...

  6. Codeforces 1037 H. Security

    \(>Codeforces \space 1037\ H. Security<\) 题目大意 : 有一个串 \(S\) ,\(q\) 组询问,每一次给出一个询问串 \(T\) 和一个区间 ...

  7. bzoj1093 [ZJOI2007]最大半联通子图 缩点 + 拓扑序

    最大半联通子图对应缩点后的$DAG$上的最长链 复杂度$O(n + m)$ #include <cstdio> #include <cstring> #include < ...

  8. Ubuntu 12.04下Hadoop 2.2.0 集群搭建(原创)

    现在大家可以跟我一起来实现Ubuntu 12.04下Hadoop 2.2.0 集群搭建,在这里我使用了两台服务器,一台作为master即namenode主机,另一台作为slave即datanode主机 ...

  9. bzoj 3872: [Poi2014]Ant colony -- 树形dp+二分

    3872: [Poi2014]Ant colony Time Limit: 30 Sec  Memory Limit: 128 MB Description   There is an entranc ...

  10. HBase EndPoint加载失败

    概述 参考博客(http://blog.csdn.net/carl810224/article/details/52224441)编写EndPoint协处理器,编写完成后使用Maven打包(使用ass ...