在OpenCL内核中设置参数会导致错误
我是OpenCL的初学者,因此编写了一个简单的程序来加倍数组的元素。 内核代码是:-在OpenCL内核中设置参数会导致错误,c,linux,parallel-processing,opencl,gpgpu,C,Linux,Parallel Processing,Opencl,Gpgpu,我是OpenCL的初学者,因此编写了一个简单的程序来加倍数组的元素。 内核代码是:- __kernel void dataParallel(__global int* A, __global int* B) { int base = get_local_id(0); B[base]=A[base]+A[base]; } 当我平方32个元素时,本地工作大小=32 在我的程序中,我声明了一个整数数组,其中包含要平方的元素 int *A; A=(int*)malloc(sizeof(
__kernel void dataParallel(__global int* A, __global int* B)
{
int base = get_local_id(0);
B[base]=A[base]+A[base];
}
当我平方32个元素时,本地工作大小=32
在我的程序中,我声明了一个整数数组,其中包含要平方的元素
int *A;
A=(int*)malloc(sizeof(int)*64);
for (i=0; i < 32; i++) { A[i] = i; }
创建上下文
cl_context context=clCreateContext(NULL,1,&devices[j],NULL,NULL,NULL);
接下来是命令队列
cl_command_queue cmdqueue=cmdqueue=clCreateCommandQueue(context,devices[j],NULL,&err);
接下来,我创建了两个内存缓冲区,一个用来保存输入数据,另一个用来保存结果
cl_mem Abuffer,Bbuffer;
Abuffer=clCreateBuffer(context, CL_MEM_READ_WRITE ,32*sizeof(int),NULL,&err);
Bbuffer=clCreateBuffer(context, CL_MEM_READ_WRITE ,32*sizeof(int),NULL,&err);
然后我将数组A的数据复制到Abuffer
ret=clEnqueueWriteBuffer(cmdqueue, Abuffer, CL_TRUE, 0, 32*sizeof(int), A, 0, NULL, NULL);
printf("%d",ret);//output is 0 thus data written successfully into the buffer
然后将内核代码读入字符串source\u str
,并创建程序
kernelprgrm=clCreateProgramWithSource(context,1,(const char **)&source_str,(const size_t *)&source_size,&err);
if(!err)
{
printf("\nKernel program created successfully\n");
}//Outputs -Kernel program created successfully
然后,我使用以下方法构建程序:
ret=clBuildProgram(kernelprgrm,1,&devices[j],NULL,NULL,NULL);//returns CL_SUCCESS
下一步获取buildinfo
ret=clGetProgramBuildInfo(kernelprgrm,devices[j], CL_PROGRAM_BUILD_STATUS ,0,NULL,&size);//Returns success
创建内核
kernel = clCreateKernel(kernelprgrm, "dataParallel", &ret);
printf("\nReturn kernel program=%d",ret);
if(!ret)
{
printf("\nProgram created successfully!\n");
}
//Outputs -Program created successfully!
现在魔鬼来了:-
ret=clSetKernelArg(kernel,0,sizeof(cl_mem),(void *) Abuffer);
printf("\nKernel argument 1 ret=%d",ret);
ret=clSetKernelArg(kernel,1,sizeof(cl_mem),(void *) Bbuffer);
printf("\nKernel argument 2 ret=%d",ret);
两者都返回-38表示CL\u无效的MEM\u对象
p.S.:根据指出的错误,即使用&Abuffer而不是参数中的Abuffer,在进行必要的更改后,两者都返回0
size_t global_item_size = 32;
size_t local_item_size = 32;
另外ret=clEnqueueNDRangeKernel(cmdqueue,kernel,1,NULL,&global\u item\u size,&local\u item\u size,0,NULL,NULL)代码>返回0
试图得到结果
ret = clEnqueueReadBuffer(cmdqueue, Bbuffer, CL_TRUE, 0, 32*sizeof(int), B, 0, NULL, NULL);`
printf("\nB:-\n");
for (t=0; t < 32; t++) {
printf("%d\t ", B[t]);
}
//如果未成功,则获取生成信息
clGetProgramBuildInfo(kernelprgrm,devices[i], CL_PROGRAM_BUILD_LOG ,0,NULL,&size);
char *buildlog=(char*)malloc(size);
clGetProgramBuildInfo(kernelprgrm,devices[i], CL_PROGRAM_BUILD_LOG ,size,buildlog,NULL);
printf("\n!!!!!!!!!!!!!!!!!!!!!Program ended!!!!!!!!!!!\n");
printf("\n\nBuildlog: %s\n\n",buildlog);
但它返回Buildlog:编译已开始
编译完成
链接开始了
链接完成
设备生成已启动
设备构建完成
内核已成功矢量化(4)
完成。
以下是OpenCL 1.2规范关于将缓冲区设置为内核参数的说明:
如果参数是内存对象(缓冲区、图像或图像数组),则arg_值项将是指向相应缓冲区、图像或图像数组对象的指针
因此,您需要传递一个指向cl\u mem
对象的指针:
ret=clSetKernelArg(kernel,0,sizeof(cl_mem),(void *) &Abuffer);
你为什么用克伦奎茨克?我认为如果你有并行工作要做,你应该使用ClenqueueEndRangeKernel。另外,只需设置全局工作大小;为本地工作组大小传递NULL。32x32比某些设备大。它正在工作!已删除1个错误。但是ret=clenqueueredbuffer(cmdqueue,Bbuffer,CL_TRUE,0,32*sizeof(int),B,0,NULL,NULL)代码>和(t=0;t<64;t++){printf(“%d\t”,B[t]);}
导致垃圾值。加上此代码在AMD平台上运行时在CPU(英特尔平台)上工作,导致分段错误@jpriceWould需要查看更多信息(例如内核排队)来尝试和诊断。将两个工作组排队将导致错误的结果。仅使用1个工作组是无效的。在这种情况下,我应该使用clenqueetask
@DarkZeros是正确的,您应该使用globa_id(0)。你不应该使用克伦奎茨克。这不是数据并行工作。这相当于运行单个工作项,在一个能够同时执行数百或数千个任务的GPU上,这是没有效率的。
clGetProgramBuildInfo(kernelprgrm,devices[i], CL_PROGRAM_BUILD_LOG ,0,NULL,&size);
char *buildlog=(char*)malloc(size);
clGetProgramBuildInfo(kernelprgrm,devices[i], CL_PROGRAM_BUILD_LOG ,size,buildlog,NULL);
printf("\n!!!!!!!!!!!!!!!!!!!!!Program ended!!!!!!!!!!!\n");
printf("\n\nBuildlog: %s\n\n",buildlog);
ret=clSetKernelArg(kernel,0,sizeof(cl_mem),(void *) &Abuffer);