OpenCL 教程 第三章 程序模型

#第三章 程序模型
创建程序的过程实际上就是将程序读入主机的过程,并将程序的内容保存在cl_program_id类型的结构体中,跟其他语言一样,我们读取程序后需要对程序进行编译和链接来创建程序,编译程序的接口如下:

cl_int clBuildProgram (cl_program program,                     //需要编译的程序对象                                   
                       cl_uint num_devices,                    //程序有关的设备列表中的设备数量
                       const cl_device_id *device_list,        //程序有关的设备列表,如果为NULL表示为所有与程序有关的设备编译程序
                       const char *options,                    //编译选项
                       void (CL_CALLBACK *pfn_notify)          //错误信息回调函数
                       (cl_program program,void *user_data),
                       void *user_data)                        //当发生错误时回调函数会访问该参数

常用的编译选项:
这里写图片描述

同样可以将编译和链接的过程分开执行:

cl_int clCompileProgram (cl_program program,                    //需要编译的程序对象
                         cl_uint num_devices,                   //程序有关的设备列表中的设备数量
                         const cl_device_id *device_list,       //程序有关的设备列表,如果为NULL表示为所有与程序有                                                                   关的设备编译程序
                         const char *options,                   //编译选项
                         cl_uint num_input_headers,             //程序文件包含的头文件数目
                         const cl_program *input_headers,       //头文件程序列表
                         const char **header_include_names,     //头文件程序名称列表
                         void (CL_CALLBACK *pfn_notify)         //错误信息回调函数
                         (cl_program program,void *user_data),  
                         void *user_data)                       //当发生错误时回调函数会访问该参数

举例:

//程序文件内容
#include <foo.h>
#include <mydir/myinc.h>
__kernel void hello (...)
{
...
}
//主机端程序内容
cl_program foo_pg = clCreateProgramWithSource(context,1, &foo_header_src, NULL, &err);
cl_program myinc_pg = clCreateProgramWithSource(context,1, &myinc_header_src, NULL, &err);
// let’s assume the program source described above is given
// by program_A and is loaded via clCreateProgramWithSource
cl_program input_headers[2] = { foo_pg, myinc_pg };
char * input_header_names[2] = { “foo.h”, “mydir/myinc.h” };
clCompileProgram(program_A ,0, NULL, // num_devices & device_list
                               NULL, // compile_options
                               2,    // num_input_headers
                               input_headers,
                               input_header_names,
                               NULL, NULL); // pfn_notify & user_data
cl_program clLinkProgram (cl_context context,                  //与设备有关的上下文  
                          cl_uint num_devices,                 //程序有关的设备列表中的设备数量
                          const cl_device_id *device_list,     //程序有关的设备列表,如果为NULL表示为所有与程序有                                                                  关的设备编译程序
                          const char *options,                 //链接选项
                          cl_uint num_input_programs,          //输入程序数量
                          const cl_program *input_programs,    //输入程序列表
                          void (CL_CALLBACK *pfn_notify)       //错误信息回调函数
                          (cl_program program,void *user_data),
                          void *user_data,                     //当发生错误时回调函数会访问该参数
                          cl_int *errcode_ret)                 //程序状态指示

当程序创建和编译完成后,我们可以通过调用接口来获取生成日志,编译信息。

cl_int clGetProgramBuildInfo (cl_program program,               //获取信息的程序对象
                              cl_device_id device,              //获取信息的设备对象
                              cl_program_build_info param_name, //获取的信息名称
                              size_t param_value_size,          //获取的信息内容大小
                              void *param_value,                //信息内容指针
                              size_t *param_value_size_ret)     //返回的信息内容大小

程序信息参数:
这里写图片描述

实验代码:

main.cpp:
#include"opencl.h"
#define filesname "hello_world.cl"
char *readKernelSourceFile(const char *filename, size_t *filelength){
    FILE *file = NULL;
    size_t source_length;
    char *source_string;
    int ret;
    file = fopen(filename, "rb");
    if (file == NULL){
        //printf("%s at %d :Can't open %s\n", __FILE__, __LINE__ - 2, filename);
        return NULL;
    }
    fseek(file, 0, SEEK_END);
    source_length = ftell(file);
    fseek(file, 0, SEEK_SET);
    source_string = (char *)malloc(source_length + 1);
    //source_string[source_length] = '\0';
    ret = fread(source_string, source_length, 1, file);
    if (ret == 0){
        printf("%s at %d :Can't read source %s \n", __FILE__, __LINE__ - 2, filename);
        return NULL;
    }
    fclose(file);
    if (source_length != 0){
        *filelength = source_length;
    }
    source_string[source_length] = '\0';
    return source_string;
}
int main(){
    cl_uint platform_num;
    clGetPlatformIDs(0, NULL, &platform_num);
    cl_platform_id *platforms = new cl_platform_id[platform_num];
    clGetPlatformIDs(platform_num, platforms, NULL);
    cl_uint device_num;
    clGetDeviceIDs(platforms[1], CL_DEVICE_TYPE_ALL, 0, NULL, &device_num);
    cl_device_id *devices = new cl_device_id[device_num];
    clGetDeviceIDs(platforms[1], CL_DEVICE_TYPE_ALL, device_num, devices, NULL);
    cl_int err;
    cl_context context = clCreateContext(NULL, device_num, devices, NULL, NULL, &err);
    checkError(err, "Can't create context");
    cl_command_queue *queues = new cl_command_queue[device_num];
    for (cl_uint i = 0; i < device_num; i++){
        queues[i] = clCreateCommandQueue(context, devices[i], CL_QUEUE_PROFILING_ENABLE, &err);
        checkError(err, "Can't create queue");
    }
    size_t file_length;
    char * files_string = readKernelSourceFile(filesname, &file_length);
    cl_program program = clCreateProgramWithSource(context, 1, (const char **)&files_string, &file_length, &err);
    checkError(err, "Failed to create program with source");
    err = clBuildProgram(program, device_num, devices, NULL, NULL, NULL);
    checkError(err, "Can't build the program");
    size_t value_size;
    clGetProgramBuildInfo(program, devices[0], CL_PROGRAM_BUILD_LOG, NULL, NULL, &value_size);
    char *bulid_value = new char[value_size];
    clGetProgramBuildInfo(program, devices[0], CL_PROGRAM_BUILD_LOG, value_size, bulid_value, NULL);
    cout << string(bulid_value) << endl;
    return 0;
}

hello_world.cl:

__kernel void hello_world(){
    int A,B;
    a+b;    //test build log
}

实验结果:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值