【问题标题】:How to pass vector parameter to OpenCL kernel in C?如何在 C 中将向量参数传递给 OpenCL 内核?
【发布时间】:2012-10-18 13:36:11
【问题描述】:

我在将向量类型 (uint8) 参数从 C 中的主机代码传递给 OpenCL 内核函数时遇到问题。

在主机中我有一个数组中的数据:

cl_uint dataArr[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };

(我的真实数据不仅仅是[1, 8];这只是为了便于解释。)

然后我将数据传输到缓冲区以传递给内核:

cl_mem kernelInputData = clCreateBuffer(context,
    CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_uint)*8, dataArr, NULL);

接下来,我将这个缓冲区传递给内核:

clSetKernelArg(kernel, 0, sizeof(cl_mem), &kernelInputData);

内核函数的签名看起来像这样:

kernel void kernelFunction(constant uint8 *vectorPtr)

但是,内核似乎没有从指向kernelInputData 的指针中获取正确的输入数据。当我从内核中传回值时,我看到vectorPtr 指向具有这种结构的东西:( 1, 2, 3, 4, 5, ?, ?, ? ) 其中问号通常4293848814,但有时是0。无论哪种方式,都不是他们应该的样子。

我做错了什么?


编辑:

我已经从使用数组切换到主机端的 cl_uint8。我现在有:

cl_uint8 dataVector = { 1, 2, 3, 4, 5, 6, 7, 8 };

然后我像这样将这个向量传递给内核:

clSetKernelArg(kernel, 0, sizeof(cl_uint8), &dataVector);

内核函数的签名看起来像这样:

kernel void kernelFunction(constant uint8 *vectorPtr)

但是,运行此代码会在clSetKernelArg() 上给我一个CL_INVALID_ARG_SIZE 错误。如果我将ARG_SIZE 参数切换为sizeof(cl_uint8 *),则此错误消失,但随后我在__dynamic_cast 中的clSetKernelArg() 中收到EXC_BAD_ACCESS 错误。

我的设备是:

Apple Macbook Pro(2009 年中)
OSX 10.8 山狮
NVIDIA GeForce 9400M
OpenCL 1.0
CLH 1.0

【问题讨论】:

  • 我不明白,你想传递一个向量还是向量数组? 'kernel void kernelFunction(constant uint8 *vectorPtr)' 请删除 *.
  • 只有一个向量。 clSetKernelArg() 的最后一个参数是 const void * 类型。
  • cl_uint8 dataVector = { 1, 2, 3, 4, 5, 6, 7, 8 }; clSetKernelArg(kernel, 0, sizeof(cl_uint8), &dataVector);kernel void kernelFunction(constant uint8 vectorPtr)
  • 哇。我曾认为所有内核函数参数都必须是指针,但显然不是。您的代码运行良好!编辑你的答案,我会标记为正确?

标签: c vector parameter-passing opencl


【解决方案1】:

您正在定义一个大小为 8 的 cl_uint 数组。 cl_mem 的创建和内核参数的设置是正确的。 但是您的内核参数不正确:您尝试读取 cl_uint8 数组而不是 cl_uint。

如果要使用向量数据类型,必须声明:cl_uint8 dataArr of size 1。 或者,如果您想使用大小为 8 的数组:kernel void kernelFunction(constant uint *vectorPtr, uint size):

编辑:

cl_uint8 dataVector 的内核参数不是指针。 所以,正确的代码是:

cl_uint8 dataVector = { 1, 2, 3, 4, 5, 6, 7, 8 };
clSetKernelArg(kernel, 0, sizeof(cl_uint8), &dataVector);

kernel void kernelFunction(constant uint8 vectorPtr)

【讨论】:

  • 啊,谢谢。我怀疑这是罪魁祸首,但我无法找到在主机代码中创建向量的任何示例。你知道该怎么做吗?
  • 请参阅opencl specification 第198页。
  • 我已经看过规格了。就像我说的,据我所知,没有从主机代码(如 cl_uint8)创建向量并用值填充它的示例。
  • cl_uint8 数组;数组.s[0] = 0;数组.s[1] = 1;数组.s[2] = 2; ... 或 cl_uint8 数组 = (cl_uint8)(0,1,2,...);
  • 啊,虽然没那么简单。我已经尝试过(cl_uint8)(0, 1, 2,...) 构造,它不能在主机上编译。您的其他构造确实 工作,就像提到的here 一样,但是当我使用clSetKernelArg(kernel, 0, sizeof(cl_uint8), &testVector) 将这样一个构造的向量传递给内核时,我得到一个EXC_BAD_ACCESS 错误。当 clSetKernelArg 的 arg_size 参数为 sizeof(cl_mem)sizeof(cl_uint *) 时,也会发生这种情况。我错过了什么?
【解决方案2】:

最小可运行示例

int2 被传递给内核。它最初被创建为cl_int 的数组。

#include <assert.h>
#include <stdlib.h>

#include <CL/cl.h>

int main(void) {
    const char *source =
        "__kernel void main(__global int2 *out) {\n"
        "      out[get_global_id(0)]++;\n"
        "}\n";
    cl_command_queue command_queue;
    cl_context context;
    cl_device_id device;
    cl_int input[] = {0, 1, 2, 3};
    const size_t global_work_size = sizeof(input) / sizeof(cl_int2);
    cl_kernel kernel;
    cl_mem buffer;
    cl_platform_id platform;
    cl_program program;

    clGetPlatformIDs(1, &platform, NULL);
    clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, NULL);
    context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);
    command_queue = clCreateCommandQueue(context, device, 0, NULL);
    buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(input), &input, NULL);
    program = clCreateProgramWithSource(context, 1, &source, NULL, NULL);
    clBuildProgram(program, 1, &device, "", NULL, NULL);
    kernel = clCreateKernel(program, "main", NULL);
    clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer);
    clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_work_size, NULL, 0, NULL, NULL);
    clFlush(command_queue);
    clFinish(command_queue);
    clEnqueueReadBuffer(command_queue, buffer, CL_TRUE, 0, sizeof(input), &input, 0, NULL, NULL);

    assert(input[0] == 1);
    assert(input[1] == 2);
    assert(input[2] == 3);
    assert(input[3] == 4);
    return EXIT_SUCCESS;
}

在 Ubuntu 15.10 OpenCL 1.2 NVIDIA 352.53 上测试。

【讨论】:

    猜你喜欢
    • 2016-07-24
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多