当前位置: 首页 > article >正文

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;
}


http://www.kler.cn/a/456208.html

相关文章:

  • Linux 文件 I/O 基础
  • Ubuntu升级ssh版本到9.8
  • 阶乘分布(Factorial Distribution)和变分推断中的均场(Mean Field)方法:中英双语
  • DeepSpeed 使用 LoRA 训练后文件结构详解
  • 3DMAX镂空星花球建模插件FloralStarBall使用方法
  • go语言的成神之路-筑基篇-gin常用功能
  • CSDN编辑器
  • 长沙景区数据分析项目实现
  • Django实现异步视图adrf请求
  • Android Studio使用BottomNavigationView实现底部导航栏demo
  • 【Ext.js 初步入门】Ext.js 作用以及用法 概述
  • 企业内训|AI大模型在汽车行业的前沿应用研修-某汽车集团
  • Java MySQL 连接
  • 自动化测试- 自动化测试模型
  • RabbitMQ - 1 ( 7000 字 RabbitMQ 入门级教程 )
  • PyTorch框架实现的简单手写数字识别模型,使用MNIST数据集进行训练和测试
  • 32单片机从入门到精通之硬件架构——总线系统(二)
  • word中文献引用[]符号的上下标格式修改
  • 【反转链表系列】力扣206,92,25
  • WINDOWS对话框模板结构简析
  • 接口自动化测试平台项目环境搭建
  • 如何使用Porcupine做一个安卓端语音唤醒demo
  • java相关学习文档或网站整理
  • 【MySQL】数据库初始化报错
  • Mono里运行C#脚本7—MonoImageStorage结构解析
  • 【Sentinel】初识Sentinel