欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

OpenCL “速成”冲刺【第一天】

发布时间:2023/12/18 36 豆豆
生活随笔 收集整理的这篇文章主要介绍了 OpenCL “速成”冲刺【第一天】 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

话说软件开发从来没有速成一说,一门语言你学的越快,说明你在别的语言上下个功夫越多,所以这次加了引号,只不过几周之后可能会有一个公司内部OpenCL的考核,虽然本人不需要考核,不过也正好借机整理下之前OpenCL的经验,一方面帮着下别的同事,一方面也给自己留点干活。这个教程针对有一点C/C++开发经验的童鞋,如果没有太多经验,我建议还是先去学学C语言。


这个是wiki上OpenCL的定义,我感觉想学OpenCL的人应该都已经知道了。

OpenCL (Open Computing Language,开放计算语言) 是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成。OpenCL由一门用于编写kernels (在OpenCL设备上运行的函数)的语言(基于C99)和一组用于定义并控制平台的API组成。OpenCL提供了基于任务分割和数据分割的并行计算机制。


第一天,环境,项目,HelloWorld


硬件环境

你需要一台支持OpenCL的设备,AMD,Nvidia的显卡,Intel的CPU(最好带核显),型号不能太老了,3年内的基本没问题。

本次教程将以Intel的CPU配合AMD的显卡为例。


软件环境

操作系统是windows的,下载安装AMDAPPSDK for windows,VS2012(老版本也行,我推荐用新的)。

操作系统是linux的,下载安装AMDAPPSDK for linux,Code::blocks(喜欢VIM的也行,或者说更好)。

下载自己常用的版本控制软件,和C/C++辅助开发软件。

PS:OpenCL也就是库和头文件,各个厂商的SDK也就是OpenCL+Tools+Samples,别的厂商也有相应的SDK,百度“厂商 OpenCL SDK"的关键字组合都能找到。


检测开发环境

安装好AMDAPPSDK之后,在命令行下运行clinfo命令,将显示出你支持OpenCL的硬件信息。

PS:不是AMD的设备,可以用CPUz,GPUz等软件查询是否支持OpenCL。


配置项目

个人认为,既然你已经知道了OpenCL就是库那么应该知道怎么配置项目,否则可能就是不满足有一点C/C++开发经验这个前提了。不过为了方便,还是贴出来。

自己去安装软件的目录下找到OpenCL库文件的位置(一般是C:\Program Files (x86)\AMD APP),linux直接find -name ”opencl“ 命令就行(一般在/opt/AMDAPP下)。

Visual Studio系列(别用VC6,不解释)

项目属性->C++->常规->附加包含目录,把SDK下边的include目录加进去。

项目属性->链接器->常规->附加库目录,把SDK下边的lib/x86_64(x64)目录加进去。

项目属性->链接器->输入->附加依赖项,输入opencl.lib

PS: 安装完SDK,一般会在系统中加入环境变量的,用环境变量配置上边的路径更方便,比如$(AMDAPPSDKROOT)include就解决了,这样换了电脑的话,只要是相同厂商就能通用。

Code::blocks

右键项目->Properties...->Project's build options,输入下边内容

-I/opt/AMDAPP/include  -L/opt/AMDAPP/lib/x86_64  -lOpenCL 

PS: 其实OpenCL就是配置好头文件和库文件,直接粘贴到项目中也行,但是不推荐,换个电脑可能就不好使了。


HelloWorld

本人偷懒就用fixstar的代码了,建立项目,新建c或者cpp文件,粘贴下列代码进去:

[cpp] view plaincopyprint?
  • #include <stdio.h>  
  • #include <stdlib.h>  
  • #include <CL/cl.h>  
  •   
  • #define MEM_SIZE (128)  
  • #define MAX_SOURCE_SIZE (0x100000)  
  •   
  • int main()  
  • {  
  •     cl_device_id device_id = NULL;  
  •     cl_context context = NULL;  
  •     cl_command_queue command_queue = NULL;  
  •     cl_mem memobj = NULL;  
  •     cl_program program = NULL;  
  •     cl_kernel kernel = NULL;  
  •     cl_platform_id platform_id = NULL;  
  •     cl_uint ret_num_devices;  
  •     cl_uint ret_num_platforms;  
  •     cl_int ret;  
  •   
  •     char string[MEM_SIZE];  
  •   
  •     FILE *fp;  
  •     char fileName[] = "./main.cl";  
  •     char *source_str;  
  •     size_t source_size;  
  •   
  •     /* Load the source code containing the kernel*/  
  •     fp = fopen(fileName, "r");  
  •     if (!fp) {  
  •         fprintf(stderr, "Failed to load kernel.\n");  
  •         exit(1);  
  •     }  
  •     source_str = (char*)malloc(MAX_SOURCE_SIZE);  
  •     source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);  
  •     fclose(fp);  
  •   
  •     /* Get Platform and Device Info */  
  •     ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);  
  •     ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices);  
  •   
  •     /* Create OpenCL context */  
  •     context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);  
  •   
  •     /* Create Command Queue */  
  •     command_queue = clCreateCommandQueue(context, device_id, 0, &ret);  
  •   
  •     /* Create Memory Buffer */  
  •     memobj = clCreateBuffer(context, CL_MEM_READ_WRITE,MEM_SIZE * sizeof(char), NULL, &ret);  
  •     /* Create Kernel Program from the source */  
  •     program = clCreateProgramWithSource(context, 1, (const char **)&source_str,(const size_t *)&source_size, &ret);  
  •   
  •     /* Build Kernel Program */  
  •     ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);  
  •   
  •     /* Create OpenCL Kernel */  
  •     kernel = clCreateKernel(program, "hello", &ret);  
  •   
  •     /* Set OpenCL Kernel Parameters */  
  •     ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);  
  •   
  •     /* Execute OpenCL Kernel */  
  •     ret = clEnqueueTask(command_queue, kernel, 0, NULL,NULL);  
  •   
  •     /* Copy results from the memory buffer */  
  •     ret = clEnqueueReadBuffer(command_queue, memobj, CL_TRUE, 0,  
  •         MEM_SIZE * sizeof(char),string, 0, NULL, NULL);  
  •   
  •     /* Display Result */  
  •     puts(string);  
  •   
  •     /* Finalization */  
  •     ret = clFlush(command_queue);  
  •     ret = clFinish(command_queue);  
  •     ret = clReleaseKernel(kernel);  
  •     ret = clReleaseProgram(program);  
  •     ret = clReleaseMemObject(memobj);  
  •     ret = clReleaseCommandQueue(command_queue);  
  •     ret = clReleaseContext(context);  
  •   
  •     free(source_str);  
  •   
  •     getchar();  
  •     return 0;  
  •   
  • }  

  • 新建文件,后缀改成.cl,粘贴下列代码进去: [cpp] view plaincopyprint?
  • __kernel void hello(__global char* string)  
  • {  
  •     string[0] = 'H';  
  •     string[1] = 'e';  
  •     string[2] = 'l';  
  •     string[3] = 'l';  
  •     string[4] = 'o';  
  •     string[5] = ',';  
  •     string[6] = ' ';  
  •     string[7] = 'W';  
  •     string[8] = 'o';  
  •     string[9] = 'r';  
  •     string[10] = 'l';  
  •     string[11] = 'd';  
  •     string[12] = '!';  
  •     string[13] = '\0';  
  • }  

  • 编译执行文件。


    第一天的内容就是这些,明天将讲解上边的代码和OpenCL的组织结构。


    作业:阅读上边的代码,解释各个API的含义,写上中文注释(最好别直接翻译),将代码上传到自己的版本管理工具上。


    总结

    以上是生活随笔为你收集整理的OpenCL “速成”冲刺【第一天】的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。