1 Star 0 Fork 0

xjDing/include

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
OpenclObj.hpp 6.79 KB
一键复制 编辑 原始数据 按行查看 历史
xjDing 提交于 2019-05-06 20:55 +08:00 . add all files
#ifndef _OPENCLOBJ_HPP_
#define _OPENCLOBJ_HPP_
#include <CL/cl.h>
#include <cstddef>
#include <fstream>
#include <sstream>
#include <cassert>
#include <string>
#include <iostream>
#include <utility>
using std::pair;
// 第 n 个平台对应数组里的 n-1
// 所有的东西都是一个,个别是多个
class OpenclObj
{
private:
cl_platform_id platform;
// pair<cl_device_id *, int> devices;
// pair<cl_context *, int> contexts;
// pair<cl_command_queue *, int> command_queues;
// pair<cl_program *, int> programs;
cl_context context;
cl_command_queue command_queue;
cl_device_id device;
cl_program program;
pair<cl_kernel *, int> kernels;
// cl_kernel *kernels;
// int num_kernel;
public:
// OpenclObj() : devices{NULL, 0}, contexts{NULL, 0},
// command_queues{NULL, 0}, programs{NULL, 0},
// kernels{NULL, 0} { platform = 0; }
OpenclObj() : kernels{NULL, 0}
{
platform = 0;
context = 0;
command_queue = 0;
device = 0;
program = 0;
}
OpenclObj(const OpenclObj &) = delete;
OpenclObj &operator=(const OpenclObj &) = delete;
~OpenclObj();
// OpenclObj(OpenclObj&& src)
// OpenclObj& operator=(OpenclObj& )
// 获取第几个平台
void GetPlatformID(int n);
// 使用设备类型创建上下文
void CreateContextFromType(cl_device_type device_type);
// 使用上下文中的第一个设备创建命令队列
void CreateCommandQueue();
// 单一源文件
void CreateProgram(const char *kernel_file, const char *options);
// 单一程序对象
void CreateKernelsInProgram();
// cl_kernel 只有8个字节, 是资源句柄
cl_kernel GetKernel(const std::string name) const;
cl_platform_id GetPlatformID() const { return platform; }
cl_context GetContext() const { return context; }
cl_device_id GetDeviceID() const { return device; }
cl_program GetProgram() const { return program; }
cl_command_queue GetCommandQueue() const { return command_queue; }
};
// 放在一起出现链接错误,重复定义 ??
/**
void OpenclObj::GetPlatformID(int n)
{
cl_int err;
cl_uint num_platform;
err = clGetPlatformIDs(0, NULL, &num_platform);
assert(err == CL_SUCCESS);
cl_platform_id *platform_idp = new cl_platform_id[num_platform];
err = clGetPlatformIDs(num_platform, platform_idp, NULL);
assert(err == CL_SUCCESS);
if (num_platform < n)
{
std::cout << "err: this pc only have " << num_platform << " platforms\n";
exit(EXIT_FAILURE);
}
platform = platform_idp[n - 1];
char name[256];
size_t info_size;
err = clGetPlatformInfo(platform, CL_PLATFORM_NAME, sizeof(name), name, NULL);
assert(err == CL_SUCCESS);
// err = clGetPlatformInfo(platform, CL_PLATFORM_NAME, info_size, name, NULL);
std::cout << "platform name: " << name << "\n";
}
void OpenclObj::CreateContextFromType(cl_device_type device_type)
{
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM,
(cl_context_properties)platform,
0};
cl_int err;
context = clCreateContextFromType(properties, device_type, NULL, NULL, &err);
assert(err == CL_SUCCESS);
}
void OpenclObj::CreateCommandQueue()
{
cl_int err;
size_t device_buffer_size;
err = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &device_buffer_size);
assert(err == CL_SUCCESS);
// 第三个参数的大小必须大于或等于第四个参数, 没办法的事情
cl_device_id *device_idp{new cl_device_id[device_buffer_size / sizeof(cl_device_id)]};
err = clGetContextInfo(context, CL_CONTEXT_DEVICES, device_buffer_size, device_idp, NULL);
assert(err == CL_SUCCESS);
cl_queue_properties properties[] = {CL_QUEUE_PROPERTIES, CL_QUEUE_PROFILING_ENABLE, 0};
// 使用上下文关联的设备中的第一个
command_queue =
clCreateCommandQueueWithProperties(context, device_idp[0], properties, &err);
assert(err == CL_SUCCESS);
device = device_idp[0];
delete[] device_idp;
char name[256];
err = clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(name), name, NULL);
assert(err == CL_SUCCESS);
std::cout << "device name: " << name << "\n";
}
void OpenclObj::CreateProgram(const char *kernel_file, const char *options)
{
cl_int err;
std::ifstream clfile{kernel_file, std::ios_base::in};
if (!clfile)
{
std::cerr << "open file error: " << kernel_file << "\n";
exit(EXIT_FAILURE);
}
std::ostringstream oss;
oss << clfile.rdbuf();
std::string src{oss.str()};
// 得到内核文件源代码
const char *srcStr{src.c_str()};
program = clCreateProgramWithSource(context, 1, (const char **)&srcStr, NULL, &err);
assert(err == CL_SUCCESS);
// std::string options{};
err = clBuildProgram(program, 1, &device, options, NULL, NULL);
if (err != CL_SUCCESS)
{
// 输出编译错误信息
size_t log_size;
err = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);
assert(err == CL_SUCCESS);
char *err_log = new char[log_size + 1];
err = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size, err_log, NULL);
assert(err == CL_SUCCESS);
err_log[log_size] = '\0';
std::cerr << "build program fail\n";
std::cerr << err_log;
clReleaseProgram(program);
delete[] err_log;
exit(EXIT_FAILURE);
}
}
void OpenclObj::CreateKernelsInProgram()
{
cl_int err;
cl_uint num_kernel;
err = clCreateKernelsInProgram(program, 0, NULL, &num_kernel);
assert(err == CL_SUCCESS);
std::cout << "there have " << num_kernel << " kernels\n";
kernels.second = static_cast<int>(num_kernel);
kernels.first = new cl_kernel[num_kernel];
err = clCreateKernelsInProgram(program, kernels.second, kernels.first, NULL);
assert(err == CL_SUCCESS);
}
cl_kernel OpenclObj::GetKernel(const std::string name) const
{
cl_int err;
char kernel_name[128];
for (int i = 0; i < kernels.second; ++i)
{
err = clGetKernelInfo(kernels.first[i], CL_KERNEL_FUNCTION_NAME,
sizeof(kernel_name), kernel_name, NULL);
assert(err == CL_SUCCESS);
if (name == std::string{kernel_name})
{
return kernels.first[i];
}
}
std::cerr << "cannot find the kernel, kernel function_name = "
<< name << "\n";
exit(EXIT_FAILURE);
}
OpenclObj::~OpenclObj()
{
if (kernels.first)
{
for (int i = 0; i < kernels.second; ++i)
clReleaseKernel(kernels.first[i]);
}
if (program)
clReleaseProgram(program);
if (command_queue)
clReleaseCommandQueue(command_queue);
if (context)
clReleaseContext(context);
}
**/
#endif
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/dingxuejun/include.git
git@gitee.com:dingxuejun/include.git
dingxuejun
include
include
master

搜索帮助