如何在C中向OpenCL内核传递向量参数?
我在从C中的宿主代码向OpenCL内核函数传递向量类型(uint8)参数时遇到问题 在主机中,我将数据存储在一个数组中:如何在C中向OpenCL内核传递向量参数?,c,vector,parameter-passing,opencl,C,Vector,Parameter Passing,Opencl,我在从C中的宿主代码向OpenCL内核函数传递向量类型(uint8)参数时遇到问题 在主机中,我将数据存储在一个数组中: 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_HO
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);
接下来,我将此缓冲区传递到内核:
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数据向量={1,2,3,4,5,6,7,8}代码>
我将这个向量传递给内核,如下所示:
clSetKernelArg(内核,0,sizeof(cl_uint8),&dataVector)代码>
内核函数的签名如下所示:
kernel void kernelFunction(constant uint8 *vectorPtr)
内核无效内核函数(常量uint8*vectorPtr)
但是,运行此代码会在clSetKernelArg()
上出现CL\u INVALID\u ARG\u SIZE
错误。如果我将ARG\u SIZE
参数切换为sizeof(cl\u uint8*)
,但随后在clSetKernelArg()
内的动态转换中出现EXC\u BAD\u访问
错误,此错误就会消失
我的设备是:
苹果MacBookPro(2009年年中)
OSX 10.8美洲狮
英伟达GeForce 9400米
OpenCL1.0
CLH 1.0您正在定义一个大小为8的CLU单元数组。
cl_mem的创建和内核参数的设置是正确的。
但是您的内核参数不正确:您尝试读取cl_uint8数组而不是cl_uint数组
如果要使用向量数据类型,必须声明:cl_uint8 dataArr,大小为1。
或者如果要使用大小为8的数组:kernelvoid kernelFunction(常量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);
及
最小可运行示例
int2
被传递到内核。它最初创建为cl\u 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;
}
#包括
#包括
#包括
内部主(空){
常量字符*源=
“uuu内核void main(uuu全局int2*out){\n”
“out[get_global_id(0)]++;\n”
“}\n”;
cl_命令_队列命令_队列;
语境;
cl_设备\u id设备;
cl_int输入[]={0,1,2,3};
const size\u t global\u work\u size=sizeof(input)/sizeof(cl\u int2);
cl_核;
cl_膜缓冲液;
cl_平台\u id平台;
CLU计划;
clGetPlatformIDs(1,&平台,NULL);
CLGetDeviceID(平台、CL_设备类型、全部、1和设备、空);
context=clCreateContext(NULL,1,&device,NULL,NULL,NULL);
command_queue=clCreateCommandQueue(上下文、设备、0、空);
buffer=clCreateBuffer(上下文,CL_MEM_READ_WRITE,CL_MEM_COPY_HOST_PTR,sizeof(输入),&input,NULL);
program=clCreateProgramWithSource(上下文,1,&source,NULL,NULL);
clBuildProgram(程序,1,&设备,”,NULL,NULL);
kernel=clCreateKernel(程序,“main”,NULL);
clSetKernelArg(内核,0,sizeof(cl_mem),&buffer);
clEnqueueNDRangeKernel(命令队列、内核、1、NULL和全局工作大小、NULL、0、NULL、NULL);
clFlush(命令队列);
clFinish(命令队列);
clenqueueredbuffer(命令队列,缓冲区,CL_TRUE,0,sizeof(输入),&input,0,NULL,NULL);
断言(输入[0]==1);
断言(输入[1]==2);
断言(输入[2]==3);
断言(输入[3]==4);
返回退出成功;
}
在Ubuntu 15.10 OpenCL 1.2 NVIDIA 352.53上测试。啊,谢谢。我怀疑这是罪魁祸首,但我还没有找到在宿主代码中创建向量的任何示例。你知道怎么做吗?请参阅198页。我已经看过规格了。正如我所说,据我所知,没有从主机代码(如cl_uint8)创建向量并用值填充它的示例。cl_uint8数组;array.s[0]=0;array.s[1]=1;array.s[2]=2。。。或cl_uint8数组=(cl_uint8)(0,1,2,…);啊,不过没那么简单。我已经尝试了(cl_uint8)(0,1,2,…)
构造,它在主机上不编译。您的另一个构造确实有效,正如前面提到的一样,但是当我使用clSetKernelArg(kernel,0,sizeof(cl\u uint8),&testVector)
将这样一个构造的向量传递给内核时,我会得到一个EXC\u BAD\u访问错误。当clSetKernelArg的arg_size参数也是sizeof(cl_mem)
和sizeof(cl_uint*)
时,就会发生这种情况。我遗漏了什么?我不明白,你想传递一个向量还是一个向量数组?”kernel void kernelFunction(常量uint8*vectorPtr)“请删除*。clSetKernelArg()
的最后一个参数的类型为const void*
cl_uint8 dataVector={1,2,3,4,5,6,7,8}代码>clSetKernelArg(内核,0,sizeof(cl_uint8),&dataVector)代码>和内核无效内核函数(常量uint8 vectorPtr)
Wow。我原以为所有的内核函数参数都必须是指针,但显然不是。你的代码运行得很好!编辑你的答案,我会标记为正确?