OpenCL无法为常量数组设置内核args

时间:2016-03-06 12:59:16

标签: c opencl nvidia

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

htpasswd

这是我内核的标题

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

2 个答案:

答案 0 :(得分:1)

来自OpenCL specification

  

指定为参数值的内存对象必须是缓冲区对象   (或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)偶然,这仍然会产生不正确的结果)。

答案 1 :(得分:0)

如果您的缓冲区永远不会更改,则不需要使用缓冲区+ __constant方式。这是另一种选择。

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

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

首选(所以请使用@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
    )

应该有相同的表现。

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