opencl: C++ 接口(cl.hpp)创建kernel

来源:互联网 发布:北师珠网络教学 编辑:程序博客网 时间:2024/06/05 08:51

OpenCL不仅提供了标准C接口,同时提供C++的接口(cl.hpp),其实就是基于C接口的进一步封装。有了这个C++接口,对于C++项目来说,就大大提高了使用的便利性,本人涉及的这个项目对OpenCL的调用全部都是基于OpenCL的C++接口来完成的。

本文讲述如何用OpenCL 1.2的C++接口来从cl原文件创建kernel。

在cl.hpp中对cl_kernel被封装成了cl::Kernel对象,当然cl_program也被封装成了cl::Program对象。创建Kernel基本上主要涉及的就是这两个对象。

要创建cl::Kernel,先要创建cl::Program,下面的代码片段从一个std::string字符串源码中创建cl::Program

/* 通过source提供的源码创建 cl::Program  */cl::Program facecl_context::createProgram(std::string source,const char* name) {    try {        // 执行clCreateProgramWithSource创建对象        // m_context为cl::Context上下文件对象        cl::Program program(m_context, source);         try{            program.build(); //代码编译 执行clBuildProgram#ifndef NDEBUG            // 获取编译日志            auto log=cl_utilits::getBuildInfo<CL_PROGRAM_BUILD_LOG>(program);            // 显示编译日志            showBuildLog(log,name);#endif            return program;        }#ifdef CL_VERSION_2_0 //当OpenCL版本为2.0以上时,编译错误抛出cl::BuildError异常// 当然要让Opencl出错时抛出异常而不是返回错误码,需要在的代码中增加__CL_ENABLE_EXCEPTIONS宏定义        catch(cl::BuildError &e){            auto log=e.getBuildLog();            showBuildLog(log,name);            // 将cl::BuildError封装成自定义异常face_cl_build_exception抛出            throw face_cl_build_exception(e,log);        }#else //当OpenCL版本为1.1,1.2时,编译错误抛出cl::Error异常        catch(cl::Error& e){            auto log=cl_utilits::getBuildInfo<CL_PROGRAM_BUILD_LOG>(program);            showBuildLog(log,name);            // 将cl::Error封装成自定义异常face_cl_build_exception抛出            throw face_cl_build_exception(e,log);        }#endif          } catch (cl::Error& e) {        // 将cl::Error 封装成自定义异常face_cl_exception抛出        throw face_cl_exception(e);    }}

有了cl::Program对象,创建cl::Kernel就更简单了

/* 通过file提供的源码创建 cl::Kernel,并将cl::Kernel命名为name加入m_kernels映射表中  */cl::Kernel facecl_context::createKernel(const char* name, const char *file) {    auto scaling = load_string(file); // 从文本文件file读取所有内存到转成std::string    auto program = createProgram(scaling,name); // 创建cl::Program对象    cl::Kernel kernel(program, name);    this->m_kernels.emplace(name, kernel);    // m_kernels类型为std::unordered_map<std::string,cl::Kernel>    return kernel;}

facecl_context 类完整的源码如下

/* * platforms.h * *  Created on: 2016年2月21日 *      Author: guyadong */#ifndef FACEDETECT_FACECL_CONTEXT_H_#define FACEDETECT_FACECL_CONTEXT_H_#include "mycl.h"#include <iostream>#include <unordered_map>#include "cl_utilits.h"#include "assert_macros.h"using namespace std;typedef enum {    image_scaling}facecl_kernel;#define KERNEL_NAME(n) #n#define KERNEL_FILE_NAME(n) #n".cl"class facecl_context {    cl::Context m_context;    cl::ImageFormat m_gray_format;    std::unordered_map<std::string,cl::Kernel> m_kernels;    cl::CommandQueue m_command_queue;    /* 初始化上下文(context),优先获取GPU设备 */    cl::Context _initContext(){    try {        return cl::Context(CL_DEVICE_TYPE_GPU);    } catch (cl::Error &e) {        if (CL_DEVICE_NOT_FOUND != e.err())            throw e;        try {            return cl::Context(CL_DEVICE_TYPE_CPU);        } catch (cl::Error &e1) {            if (CL_DEVICE_NOT_FOUND != e1.err())                throw e1;            return cl::Context(CL_DEVICE_TYPE_DEFAULT);        }    }}public:    void showSupportedImageFormats(cl_mem_flags flags,            cl_mem_object_type type = CL_MEM_OBJECT_IMAGE2D,            std::ostream& stream = cout) {        return cl_utilits::showSupportedImageFormats(m_context, flags, type, cout);    }    const cl::Context& getContext()const{        return m_context;    }    const cl::ImageFormat& getGrayFormat()const{        return m_gray_format;    }    const cl::Kernel& getKernel(const char* name)const{        auto itor=m_kernels.find(std::string(name));        if(itor==m_kernels.end())            throw face_cl_exception(ERROR_STR("can't found kernel:").append(name));        return  itor->second;    }    cl::CommandQueue &getCommandQueue(){        return m_command_queue;    }    cl::Program createProgram(std::string src,const char* name=nullptr) {        try {            cl::Program program(m_context, source);            try{                program.build();    #ifndef NDEBUG                auto log=cl_utilits::getBuildInfo<CL_PROGRAM_BUILD_LOG>(program);                showBuildLog(log,name);    #endif                return program;            }    #ifdef CL_VERSION_2_0 //当OpenCL版本为2.0以上时,编译错误抛出cl::BuildError异常            catch(cl::BuildError &e){                auto log=e.getBuildLog();                showBuildLog(log,name);                throw face_cl_build_exception(e,log);            }    #else //当OpenCL版本为1.1,1.2时,编译错误抛出cl::Error异常            catch(cl::Error& e){                auto log=cl_utilits::getBuildInfo<CL_PROGRAM_BUILD_LOG>(program);                showBuildLog(log,name);                throw face_cl_build_exception(e,log);            }    #endif        } catch (cl::Error& e) {            throw face_cl_exception(e);        }    }    cl::Kernel createKernel(const char* name, const char* file){        auto scaling = load_string(file);        auto program = createProgram(scaling,name);        cl::Kernel kernel(program, name);        this->m_kernels.emplace(name, kernel);        return kernel;    }    void showBuildLog(build_log_type& build_log, const char* name = nullptr, std::ostream& stream=cout) {        if (name)            stream<<"--------------" << "source name:" << name<<"------------------" << endl;        cl_utilits::showBuildLog(build_log, stream);    }    facecl_context(){        try{            m_context = _initContext();            auto devices = m_context.getInfo<CL_CONTEXT_DEVICES>();            m_command_queue=cl::CommandQueue(m_context);            cl_utilits::showDevices(devices);            m_gray_format = cl_utilits::getFittedImageFormatForGray(m_context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR);            cout << "select format:" << cl_utilits::imageFormatToString(m_gray_format) << endl;            auto k=createKernel(KERNEL_NAME(image_scaling),KERNEL_FILE_NAME(image_scaling));        }catch(exception&e){            cout<<e.what()<<endl;            throw e;        }    }    virtual ~facecl_context()=default;};extern facecl_context global_facecl_context;#endif /* FACEDETECT_FACECL_CONTEXT_H_ */
0 0
原创粉丝点击