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中。
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);
}
程序清单4.12 查询程序对象编译日志的函数封装
4.6.2 创建一个程序字符串
第3章中,我们使用了字符数组(const char **strings),调用clCreateProgramWithSource()
创建程序对象。不过,将OpenCL C源直接携程字符数组是十分不便的。因此,通常的做法都是将OpenCL C源码放置在一个单独文件中,当主机端使用到的时候对改文件进行读取。
使用C++时(如代码清单4.8所示),从文件中读取字符串就简单很多。不过,当我们使用C语言时,从文件中读取字符串就需要多做一些事情。代码清单4.13就展示了,如何使用一个C函数将文件读取到一个C的字符串(字符数组)中。
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;
}
程序清单4.13 将OpenCL C源码从文件中读取出