跳转至

两个clCreateKernel函数

clCreateKernel函数会生成编译生成最终的二进制汇编。

clCreateKernelclCreateKernelsInProgram 都是 OpenCL 中用于创建内核对象的函数,但它们在功能和使用场景上存在明显区别,下面为你详细介绍:

功能用途

  • clCreateKernel:此函数用于从 clProgram 对象里创建单个内核对象。当你确切知道要使用的内核函数名时,就可以使用这个函数。
  • clCreateKernelsInProgram:该函数用于从 clProgram 对象中创建所有内核对象。当你想一次性获取程序里的所有内核,而不是逐个指定内核函数名时,就适合使用这个函数。

函数原型

C++
// clCreateKernel
cl_kernel clCreateKernel(cl_program program, const char *kernel_name, cl_int *errcode_ret);

// clCreateKernelsInProgram
cl_int clCreateKernelsInProgram(cl_program program, cl_uint num_kernels, cl_kernel *kernels, cl_uint *num_kernels_ret);

参数解释

  • clCreateKernel
  • program:代表包含内核函数的 clProgram 对象。
  • kernel_name:是一个字符串,代表要创建的内核函数名。
  • errcode_ret:用于返回错误码。
  • clCreateKernelsInProgram
  • program:代表包含内核函数的 clProgram 对象。
  • num_kernels:表示调用者预期创建的内核数量。如果传入 0kernels 可以设为 NULL,函数会返回程序里的内核总数。
  • kernels:是一个指向 cl_kernel 数组的指针,用于存储创建的内核对象。
  • num_kernels_ret:用于返回实际创建的内核数量。

示例代码

C++
#include <CL/cl.h>
#include <stdio.h>
#include <stdlib.h>

// OpenCL kernel source code
const char *kernelSource = "__kernel void add(__global const int *a, __global const int *b, __global int *c) { \n"
                           "    int gid = get_global_id(0); \n"
                           "    c[gid] = a[gid] + b[gid]; \n"
                           "} \n"
                           "__kernel void subtract(__global const int *a, __global const int *b, __global int *c) { \n"
                           "    int gid = get_global_id(0); \n"
                           "    c[gid] = a[gid] - b[gid]; \n"
                           "} \n";

int main() {
    // Create an OpenCL context
    cl_platform_id platform;
    cl_device_id device;
    cl_context context;
    clGetPlatformIDs(1, &platform, NULL);
    clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
    context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);

    // Create an OpenCL program
    cl_program program = clCreateProgramWithSource(context, 1, (const char **)&kernelSource, NULL, NULL);
    clBuildProgram(program, 1, &device, NULL, NULL, NULL);

    // 使用 clCreateKernel 创建单个内核
    cl_kernel add_kernel = clCreateKernel(program, "add", NULL);

    // 使用 clCreateKernelsInProgram 创建所有内核
    cl_uint num_kernels;
    clCreateKernelsInProgram(program, 0, NULL, &num_kernels);
    cl_kernel *all_kernels = (cl_kernel *)malloc(num_kernels * sizeof(cl_kernel));
    clCreateKernelsInProgram(program, num_kernels, all_kernels, NULL);

    // Clean up
    clReleaseKernel(add_kernel);
    for (cl_uint i = 0; i < num_kernels; i++) {
        clReleaseKernel(all_kernels[i]);
    }
    free(all_kernels);
    clReleaseProgram(program);
    clReleaseContext(context);

    return 0;
}

总结

  • 若你清楚要使用的内核函数名,且只需要创建一个内核对象,就使用 clCreateKernel
  • 若你想一次性获取程序里的所有内核对象,就使用 clCreateKernelsInProgram