第4章 OpenCL案例 - 4.6 基本功能函数

优质
小牛编辑
126浏览
2023-12-01

因为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(“%sn”, 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: %sn”, filename);
exit(-1);
}

/ Determine the file size /
if (fseek(fp, 0, SEEK_END)){
printf(“Error read the filen”);
exit(-1);
}
fileSize = ftell(fp);
if (fileSize < 0){
printf(“Error read the filen”);
exit(-1);
}
if (fseek(fp, 0, SEEK_SET)){
printf(“Error read the filen”);
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 filen”);
exit(-1);
}

/ Terminate the string /
fileData[fileSize] = ‘’;

/ Close the file /
if (fclose(fp)){
printf(“Error closing the filen”);
exit(-1);
}

return fileData;
}
{%endace%}

程序清单4.13 将OpenCL C源码从文件中读取出