opencl 封装简单api

这是cl代码

kernel.c

cpp 复制代码
__kernel void add_one(__global float *output,__global  float* pnum) 
{
    int x=get_global_id(0);
    output[x]+=pnum[0];
}

c代码

cpp 复制代码
#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;
}
相关推荐
寻星探路5 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
曹牧7 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法8 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
七夜zippoe8 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann