本专栏是通过注解程序的方法学习OpenCL,我觉得一个一个地去抠原理也不是办法,干脆直接学习程序,然后把相关原理都直接注解到程序语句当中。
原创地址:http://blog.csdn.net/kenden23/article/details/14101657
一开始要配置好环境,我的是nvidia,所以就按照我的电脑举例,AMD应该也差不多。
1. 首先要到nvidia网站下载适合你显卡的最新驱动,安装好
2. 还是在nvidia网站下载好CUDA开发包,安装好
3. 如果默认安装路径的话,路径应该是在:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0
4. 打开这个目录会发现里面有include和lib文件夹,这就是我们需要配置在visual studio中的文件
5. 打开visual studio(版本基本都无关系,我用的是vs2012),新建一个win32空项目。按下alt+F7打开项目属性,也可以点击项目文件右键,选择属性。
6. 在属性页里面找到“C/C++”的“常规”项,点击,右边有“附加包含目录”,然后编辑,添加目录:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0\include
7.在属性页里面找到“连接器”,点击其“常规”项,右边有“附加库目录”,然后也是编辑,添加目录:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0\lib\Win32,如果是64位系统可以是:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0\lib\x64。
8. 在属性页里找到“常规”项, 右边“附加依赖项”,编辑,添加lib文件:OpenCL.lib
9. 然后就可以新建源文件,在源文件里面添加相关的OpenCl程序,就可以调试OpenCL程序了。
下面就可以开始学习程序了。
下面是个入门程序,已经注释好了,注释包括了基本原理的解析,可以通过直接阅读和调试程序学习OpenCL了。
本程序是读取电脑中的支持OpenCL的硬件nvidia和intel和AMD等信息,然后显示在屏幕上。
[cpp] view plain
copy
print ?
- #include
- #include
- #include
- #include
-
- #ifdef MAC
- #include
- #else
- #include
- #endif
-
- int main() {
-
-
- cl_platform_id *platforms;
-
- cl_uint num_platforms;
- cl_int i, err, platform_index = -1;
-
-
- char* ext_data;
- size_t ext_size;
- const char icd_ext[] = "cl_khr_icd";
-
-
-
-
-
-
-
- err = clGetPlatformIDs(5, NULL, &num_platforms);
- if(err < 0) {
- perror("Couldn't find any platforms.");
- exit(1);
- }
-
- printf("I have platforms: %d\n", num_platforms);
-
-
-
- platforms = (cl_platform_id*)
- malloc(sizeof(cl_platform_id) * num_platforms);
-
- clGetPlatformIDs(num_platforms, platforms, NULL);
-
-
-
-
- for(i=0; i
- {
-
-
- err = clGetPlatformInfo(platforms[i],
- CL_PLATFORM_EXTENSIONS, 0, NULL, &ext_size);
- if(err < 0)
- {
- perror("Couldn't read extension data.");
- exit(1);
- }
-
- printf("The size of extension data is: %d\n", ext_size);
-
-
-
- ext_data = (char*)malloc(ext_size);
-
- clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS,
- ext_size, ext_data, NULL);
- printf("Platform %d supports extensions: %s\n", i, ext_data);
-
-
- char *name = (char*)malloc(ext_size);
- clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME,
- ext_size, name, NULL);
- printf("Platform %d name: %s\n", i, name);
-
-
- char *vendor = (char*)malloc(ext_size);
- clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR,
- ext_size, vendor, NULL);
- printf("Platform %d vendor: %s\n", i, vendor);
-
-
- char *version = (char*)malloc(ext_size);
- clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION,
- ext_size, version, NULL);
- printf("Platform %d version: %s\n", i, version);
-
-
- char *profile = (char*)malloc(ext_size);
- clGetPlatformInfo(platforms[i], CL_PLATFORM_PROFILE,
- ext_size, profile, NULL);
- printf("Platform %d full profile or embeded profile?: %s\n", i, profile);
-
-
-
- if(strstr(ext_data, icd_ext) != NULL)
- platform_index = i;
- std::cout<<"Platform_index = "<
-
- if(platform_index > -1)
- printf("Platform %d supports the %s extension.\n",
- platform_index, icd_ext);
-
- std::cout<
-
-
- free(ext_data);
- free(name);
- free(vendor);
- free(version);
- free(profile);
- }
-
- if(platform_index <= -1)
- printf("No platforms support the %s extension.\n", icd_ext);
-
-
- free(platforms);
- return 0;
- }
每个电脑的输出结果不一样的,我电脑的输出结果是:
OpenCL 查看设备信息
下面是注释程序,目的就是查看自己计算机上所有支持OpenCL的设备,并打印信息。
主函数调用run()就可以运行了。要设置请看我另一篇OpenCl设置文章。
[cpp] view plain
copy
print ?
- #include
- #include
- #include
-
- #ifdef MAC
- #include
- #else
- #include
- #endif
-
- namespace device_ext_test
- {
-
- int run() {
-
- cl_platform_id *platforms;
- cl_device_id *devices;
- cl_uint num_platforms;
- cl_uint num_devices, addr_data;
- cl_int i, err;
-
-
- char name_data[48], ext_data[4096];
-
- err = clGetPlatformIDs(5, NULL, &num_platforms);
- if(err < 0) {
- perror("Couldn't find any platforms.");
- exit(1);
- }
-
-
- platforms = (cl_platform_id*)
- malloc(sizeof(cl_platform_id) * num_platforms);
- err = clGetPlatformIDs(num_platforms, platforms, NULL);
- if(err < 0) {
- perror("Couldn't find any platforms");
- exit(1);
- }
-
-
-
- for (int j = 0; j < (int)num_platforms; j++)
- {
- printf("\nplatform %d\n", j+1);
-
- err = clGetDeviceIDs(platforms[j], CL_DEVICE_TYPE_ALL, 1, NULL, &num_devices);
- if(err < 0) {
- perror("Couldn't find any devices");
- exit(1);
- }
-
-
- devices = (cl_device_id*)
- malloc(sizeof(cl_device_id) * num_devices);
- clGetDeviceIDs(platforms[j], CL_DEVICE_TYPE_ALL,
- num_devices, devices, NULL);
-
-
- for(i=0; i<(int)num_devices; i++) {
-
- err = clGetDeviceInfo(devices[i], CL_DEVICE_NAME,
- sizeof(name_data), name_data, NULL);
- if(err < 0) {
- perror("Couldn't read extension data");
- exit(1);
- }
- clGetDeviceInfo(devices[i], CL_DEVICE_ADDRESS_BITS,
- sizeof(ext_data), &addr_data, NULL);
-
- clGetDeviceInfo(devices[i], CL_DEVICE_EXTENSIONS,
- sizeof(ext_data), ext_data, NULL);
-
- printf("NAME: %s\nADDRESS_WIDTH: %u\nEXTENSIONS: %s\n\n",
- name_data, addr_data, ext_data);
- }
- }
-
- free(platforms);
- free(devices);
- printf("\n");
- system("pause");
- return 0;
- }
-
-
- }
OpenCL 操作context
本程序主要测试:
context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
创建一个context
clRetainContext(context);//Context的reference +1
clReleaseContext(context);//Context的reference -1
[cpp] view plain
copy
print ?
- #include
- #include
- #include
-
- #ifdef MAC
- #include
- #else
- #include
- #endif
-
- namespace context_count
- {
-
- int run()
- {
- cl_platform_id platform;
- cl_device_id device;
- cl_context context;
- cl_int err;
- cl_uint ref_count;
-
- err = clGetPlatformIDs(1, &platform, NULL);
- if(err < 0) {
- perror("Couldn't find any platforms");
- exit(1);
- }
-
- err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
- if(err == CL_DEVICE_NOT_FOUND) {
- err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 1, &device, NULL);
- }
- if(err < 0) {
- perror("Couldn't find any devices");
- exit(1);
- }
-
-
- context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
- if(err < 0) {
- perror("Couldn't create a context");
- exit(1);
- }
-
-
- err = clGetContextInfo(context, CL_CONTEXT_REFERENCE_COUNT,
- sizeof(ref_count), &ref_count, NULL);
- if(err < 0) {
- perror("Couldn't read the reference count.");
- exit(1);
- }
- printf("Initial reference count: %u\n", ref_count);
-
-
- clRetainContext(context);clRetainContext(context);
- clGetContextInfo(context, CL_CONTEXT_REFERENCE_COUNT,
- sizeof(ref_count), &ref_count, NULL);
- printf("Reference count: %u\n", ref_count);
-
- clReleaseContext(context);
- clGetContextInfo(context, CL_CONTEXT_REFERENCE_COUNT,
- sizeof(ref_count), &ref_count, NULL);
- printf("Reference count: %u\n", ref_count);
-
- clReleaseContext(context);clReleaseContext(context);
- system("pause");
- return 0;
- }
-
- }
OpenCL 获取Program信息
本程序生成一个OpenCL Program,然后获取Program的source,其实它的source就是一个char[],可以打印出来。
然后我们把这些内容和原来文本的内容对比,看看是否是我们想要读入的内容。
还可以测试是否编译正确,如果不正确会有输出提示的。
下面程序运行如下:
前面都是读入的函数代码。然后后面检查这些函数是否正确,可以看到第二个函数不正确,因为*r没有定义。
下面是完整代码:
[cpp] view plain
copy
print ?
- #define _CRT_SECURE_NO_WARNINGS
-
- #include
- #include
- #include
-
- #ifdef MAC
- #include
- #else
- #include
- #endif
-
- namespace program_build
- {
-
- const static int NUM_FILES = 2;
- const char PROGRAM_FILE_1[] = "good.cl";
- const char *PROGRAM_FILE_2 = "bad.cl";
-
- int run()
- {
-
-
-
-
- cl_platform_id platform;
- cl_device_id device;
- cl_context context;
- cl_int i, err;
-
-
- cl_program program;
- FILE *program_handle;
- char *program_buffer[NUM_FILES];
- char *program_log;
- const char *file_name[] = {PROGRAM_FILE_1, PROGRAM_FILE_2};
- const char options[] = "-cl-finite-math-only -cl-no-signed-zeros";
- size_t program_size[NUM_FILES];
- size_t log_size;
-
-
- err = clGetPlatformIDs(1, &platform, NULL);
- if(err < 0) {
- perror("Couldn't find any platforms");
- exit(1);
- }
-
-
- err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
- if(err == CL_DEVICE_NOT_FOUND) {
- err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 1, &device, NULL);
- }
- if(err < 0) {
- perror("Couldn't find any devices");
- exit(1);
- }
-
-
- context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
- if(err < 0) {
- perror("Couldn't create a context");
- exit(1);
- }
-
-
- for(i=0; i
-
- program_handle = fopen(file_name[i], "r");
- if(program_handle == NULL) {
- perror("Couldn't find the program file");
- exit(1);
- }
- fseek(program_handle, 0, SEEK_END);
- program_size[i] = ftell(program_handle);
- rewind(program_handle);
- program_buffer[i] = (char*)malloc(program_size[i]+1);
- program_buffer[i][program_size[i]] = '\0';
- fread(program_buffer[i], sizeof(char), program_size[i],
- program_handle);
- fclose(program_handle);
- }
-
-
- program = clCreateProgramWithSource(context, NUM_FILES,
- (const char**)program_buffer, program_size, &err);
- if(err < 0) {
- perror("Couldn't create the program");
- exit(1);
- }
-
-
-
-
-
- err = clBuildProgram(program, 1, &device, options, NULL, NULL);
-
- int bufSize = program_size[0] + program_size[1] + 1;
- char *programBuffer = (char *) malloc(bufSize);
- clGetProgramInfo(program, CL_PROGRAM_SOURCE, bufSize, programBuffer, NULL);
- printf("Print Program Source:\n");
- printf("\n %s \n", programBuffer);
-
- printf("Check if it is correct:\n");
- for (int i = 0; i < NUM_FILES; i++)
- {
- printf("\n %s \n", program_buffer[i]);
- }
-
- if(err < 0)
- {
- clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,
- 0, NULL, &log_size);
- program_log = (char*) malloc(log_size+1);
- program_log[log_size] = '\0';
- clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,
- log_size+1, program_log, NULL);
- printf("%s\n", program_log);
- free(program_log);
- system("pause");
- exit(1);
- }
-
-
- for(i=0; i
- free(program_buffer[i]);
- }
- clReleaseProgram(program);
- clReleaseContext(context);
- system("pause");
-
- return 0;
- }
-
- }