opencl 封装简单api
这是cl代码
kernel.c
__kernel void add_one(__global float *output,__global float* pnum)
{
int x=get_global_id(0);
output[x]+=pnum[0];
}
c代码
#include <CL/cl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<stdarg.h>
typedef struct {
cl_platform_id platform_id;
cl_device_id device_id;
cl_context context;
cl_command_queue command_queue;
cl_program program;
cl_kernel kernel;
cl_mem mem_objects[10]; // 假设最多有10个内存对象
int mem_count;
} OpenCLContext;
// 初始化OpenCL上下文
void cl_init(OpenCLContext *ctx) {
cl_int err;
ctx->mem_count = 0;
// 获取平台ID
clGetPlatformIDs(1, &ctx->platform_id, NULL);
// 获取设备ID
clGetDeviceIDs(ctx->platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &ctx->device_id, NULL);
// 创建上下文
ctx->context = clCreateContext(NULL, 1, &ctx->device_id, NULL, NULL, &err);
if (err != CL_SUCCESS) {
fprintf(stderr, "Failed to create OpenCL context\n");
exit(EXIT_FAILURE);
}
// 创建命令队列
ctx->command_queue = clCreateCommandQueue(ctx->context, ctx->device_id, 0, &err);
if (err != CL_SUCCESS) {
fprintf(stderr, "Failed to create OpenCL command queue\n");
exit(EXIT_FAILURE);
}
//ctx->command_queue=1;
}
// 加载OpenCL程序
void cl_load(OpenCLContext *ctx, const char *source,char*funcname) {
cl_int err;
// 创建程序
ctx->program = clCreateProgramWithSource(ctx->context, 1, (const char **)&source, NULL, &err);
if (err != CL_SUCCESS) {
fprintf(stderr, "Failed to create OpenCL program\n");
exit(EXIT_FAILURE);
}
// 构建程序
err = clBuildProgram(ctx->program, 1, &ctx->device_id, NULL, NULL, NULL);
if (err != CL_SUCCESS) {
char build_log[1024];
clGetProgramBuildInfo(ctx->program, ctx->device_id, CL_PROGRAM_BUILD_LOG, sizeof(build_log), build_log, NULL);
fprintf(stderr, "Failed to build OpenCL program:\n%s\n", build_log);
exit(EXIT_FAILURE);
}
// 创建内核
ctx->kernel = clCreateKernel(ctx->program, funcname, &err); // 假设内核名为my_kernel
if (err != CL_SUCCESS) {
fprintf(stderr, "Failed to create OpenCL kernel\n");
exit(EXIT_FAILURE);
}
}
// 分配OpenCL内存
cl_mem cl_malloc(OpenCLContext *ctx, size_t size) {
cl_int err;
cl_mem mem = clCreateBuffer(ctx->context, CL_MEM_READ_WRITE, size, NULL, &err);
if (err == CL_SUCCESS && ctx->mem_count < 10) {
ctx->mem_objects[ctx->mem_count++] = mem;
} else {
fprintf(stderr, "Failed to allocate OpenCL memory\n");
exit(EXIT_FAILURE);
}
return mem;
}
// 向OpenCL内存写入数据
void cl_write(OpenCLContext *ctx, cl_mem mem, const void *data, size_t size) {
cl_int err;
err = clEnqueueWriteBuffer(ctx->command_queue, mem, CL_TRUE, 0, size, data, 0, NULL, NULL);
if (err != CL_SUCCESS) {
fprintf(stderr, "Failed to write to OpenCL memory\n");
exit(EXIT_FAILURE);
}
}
// 从OpenCL内存读取数据
void cl_read(OpenCLContext *ctx, cl_mem mem, void *data, size_t size) {
cl_int err;
err = clEnqueueReadBuffer(ctx->command_queue, mem, CL_TRUE, 0, size, data, 0, NULL, NULL);
if (err != CL_SUCCESS) {
fprintf(stderr, "Failed to read from OpenCL memory\n");
exit(EXIT_FAILURE);
}
}
// 执行OpenCL内核
void cl_exec(OpenCLContext *ctx, size_t global_work_size, size_t local_work_size, int num_args, ...) {
va_list args;
cl_int err;
va_start(args, num_args);
for (int i = 0; i < num_args; i++) {
cl_mem mem = va_arg(args, cl_mem);
err = clSetKernelArg(ctx->kernel, i, sizeof(cl_mem), (void *)&mem);
if (err != CL_SUCCESS) {
fprintf(stderr, "Failed to set OpenCL kernel argument\n");
exit(EXIT_FAILURE);
}
}
va_end(args);
err = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel, 1, NULL, &global_work_size, &local_work_size, 0, NULL, NULL);
if (err != CL_SUCCESS) {
fprintf(stderr, "Failed to execute OpenCL kernel\n");
exit(EXIT_FAILURE);
}
// 等待命令队列完成(可选,取决于是否需要同步)
clFinish(ctx->command_queue);
}
// 释放OpenCL资源
void cl_free(OpenCLContext *ctx) {
for (int i = 0; i < ctx->mem_count; i++) {
clReleaseMemObject(ctx->mem_objects[i]);
}
clReleaseKernel(ctx->kernel);
clReleaseProgram(ctx->program);
clReleaseCommandQueue(ctx->command_queue);
clReleaseContext(ctx->context);
}
int main() {
OpenCLContext ctx;
//cl_int err;
// 初始化OpenCL上下文
cl_init(&ctx);
char code[512];
memset(&code,0,sizeof(code));
// OpenCL内核源代码(这里应该是一个完整的内核函数定义)
const char *kernel_source = &code;
FILE*f=fopen("kernel.cl","rb");
fread(code,sizeof(code),1,f);
fclose(f);
// 加载OpenCL程序
cl_load(&ctx, kernel_source,"add_one");
// 分配OpenCL内存
float data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
cl_mem buffer = cl_malloc(&ctx, sizeof(data));
cl_mem buf2=cl_malloc(&ctx,sizeof(float));
float f2=1;
// 向OpenCL内存写入数据
cl_write(&ctx, buffer, data, sizeof(data));
cl_write(&ctx,buf2,&f2,sizeof(float));
// 执行OpenCL内核
size_t global_work_size = 10;
size_t local_work_size = 1;
cl_exec(&ctx, global_work_size, local_work_size, 2, buffer,buf2);
// 从OpenCL内存读取数据
float result[10];
cl_read(&ctx, buffer, result, sizeof(result));
// 打印结果
for (int i = 0; i < 10; i++) {
printf("%f\n", result[i]); // 应该打印出2, 4, 6, 8, 10, 12, 14, 16, 18, 20
}
puts("-----------------");
//cl_write(&ctx, buffer, data, sizeof(data));
f2=2;
cl_write(&ctx,buf2,&f2,sizeof(float));
// 执行OpenCL内核
cl_exec(&ctx, global_work_size, local_work_size, 2, buffer,buf2);
// 从OpenCL内存读取数据
cl_read(&ctx, buffer, result, sizeof(result));
// 打印结果
for (int i = 0; i < 10; i++) {
printf("%f\n", result[i]); // 应该打印出2, 4, 6, 8, 10, 12, 14, 16, 18, 20
}
puts("-----------------");
// 释放OpenCL资源
cl_free(&ctx);
return 0;
}