4.6 基本功能函数
因为OpenCL意味着对于系统来说是不可知的,有些任务不能像传统的C/C++那样自动完成。不过好消息是当相关工具代码完成后,就可以是用到所有OpenCL应用代码中。
4.6.1 打印编译错误信息
当我们尝试编译和链接我们的OpenCL程序对象时(使用clBuildProgram()
、clCompileProgram()
和clLinkProgram()
),OpenCL C代码可能会出现错误。出现错误时,主机端不会直接显示这些编译错误,而是直接退出。通过OpenCL API的返回值,让编程者知道是编译时候的错误,并需要手动去将编译输出打印出来。
当OpenCL程序对象编译失败,一个构建日志将会产生,并保存在程序对象中。该日志可以通过API clGetProgramBuildInfo()
检索出,传入CL_PROGRAM_BUILD_LOG到param_name,得到相应日志内容。还有与其类似的API存在,clProgramBuildInfo()
需要调用两次:第一次是获取日志的大小,分配对应大小的数组,用来放置日志内容;第二次是将日志中的具体内容取出。
本章中我们自己封装了一个名为printCompilerError()的函数,用于打印OpenCL C的编译错误信息。printCompilerError()的具体实现在程序清单4.12中。
{%ace edit=false, lang=’c_cpp’%} void printCompilerError(cl_program program, cl_device_id device) { cl_int status;
size_t logSize; char *log;
/ Get the log size / status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logSize); check(status);
/ Allocate space for the log / log = (char *)malloc(logSize); if (!log){ exit(-1); }
/ Read the log / status = clGetPeogramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, logSize, log, NULL); check(status);
/ Print the log / printf(“%s\n”, log); } {%endace%}
程序清单4.12 查询程序对象编译日志的函数封装
4.6.2 创建一个程序字符串
第3章中,我们使用了字符数组(const char **strings),调用clCreateProgramWithSource()
创建程序对象。不过,将OpenCL C源直接携程字符数组是十分不便的。因此,通常的做法都是将OpenCL C源码放置在一个单独文件中,当主机端使用到的时候对改文件进行读取。
使用C++时(如代码清单4.8所示),从文件中读取字符串就简单很多。不过,当我们使用C语言时,从文件中读取字符串就需要多做一些事情。代码清单4.13就展示了,如何使用一个C函数将文件读取到一个C的字符串(字符数组)中。
{%ace edit=false, lang=’c_cpp’%} char readFile(const char filename) { FILE fp; char fileData; long fileSize;
/ Open the file / fp = fopen(filename, “r”); if (!fp){ printf(“Could not open file: %s\n”, filename); exit(-1); }
/ Determine the file size / if (fseek(fp, 0, SEEK_END)){ printf(“Error read the file\n”); exit(-1); } fileSize = ftell(fp); if (fileSize < 0){ printf(“Error read the file\n”); exit(-1); } if (fseek(fp, 0, SEEK_SET)){ printf(“Error read the file\n”); exit(-1); }
/ Read the contents / fileData = (char *)malloc(fileSize + 1); if (!fileData){ exit(-1); } if (fread(fileData, fileSize, 1, fp) != 1){ printf(“Error reading the file\n”); exit(-1); }
/ Terminate the string / fileData[fileSize] = ‘\0’;
/ Close the file / if (fclose(fp)){ printf(“Error closing the file\n”); exit(-1); }
return fileData; } {%endace%}
程序清单4.13 将OpenCL C源码从文件中读取出