c语言 - OpenCL 无法为常量数组设置内核参数



我正在尝试设置内核的参数,当我尝试设置边界 arg-0 时,我不断遇到CL_INVALID_ARG_SIZE。奇怪的是,如果我只是注释掉第一个 clSetKernelArgs,所有其他似乎都可以工作。 我认为这可能是常量数组的问题,除了它适用于rand_seeds。

success = clSetKernelArg(solver_kernel, 0, sizeof(cl_float) * 10, bounds);
    if(success != CL_SUCCESS)
    {
        printf("%dn", success);
        exit(1);
    }
    success = clSetKernelArg(solver_kernel, 1, sizeof(cl_float) * 2, seeds);
    if(success != CL_SUCCESS)
    {
        printf("%dn", success);
        exit(1);
    }
    success = clSetKernelArg(solver_kernel, 2, sizeof(cl_int), &trials);
    if(success != CL_SUCCESS)
    {
        printf("%dn", success);
        exit(1);
    }
    success = clSetKernelArg(solver_kernel, 3, sizeof(cl_int), &start_temp);
    if(success != CL_SUCCESS)
    {
        printf("%dn", success);
        exit(1);
    }

这是我内核的标头

  __kernel void solver_kernel
    (
        __constant float bounds[10],
        __constant int rand_seeds[2],
        int trials,
        int start_temp
    )

来自 OpenCL 规范:

指定为参数值的内存对象必须是缓冲区对象 (或 NULL),如果参数声明为内置或 具有__global__constant限定符的用户定义类型。

因此,您必须首先创建一个缓冲区并将其设置为内核参数。应该看起来像这样

cl_mem bounds_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_float) * 10, bounds, &success); 
success = clSetKernelArg(solver_kernel, 0, sizeof(cl_mem), bounds_buffer);

您需要对rand_seeds参数执行相同的操作,即使您在此行没有收到错误(可能是偶然sizeof(cl_float) * 2 == sizeof(cl_mem),这仍然会产生不正确的结果)。

如果您的缓冲区永远不会改变,则无需使用缓冲区 + __constant方式。这是一个替代方案。

实际上有两种方法可以在内核中使用常量内存:

  • 使用标准缓冲区 + __constant标志
  • 使用结构参数

第一个是首选(因此请使用@Jan接受的答案),因为您明确表示您希望如何处理数据。但实际上,对于第二种情况,所有实现也使用常量内存。由于它传递给内核的数据是静态的,无论如何都不可修改。

因此,您可以像以下方式重写内核:

 typedef struct float_10 { float f[10];} float_10;
 typedef struct int_2 { int i[2];}int_2;
  __kernel void solver_kernel
    (
        float_10 bounds,
        int_2 rand_seeds,
        int trials,
        int start_temp
    )

应具有相同的性能。

编辑:因为你需要结构,而不是数组

最新更新