Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在OpenCL内核中设置参数会导致错误_C_Linux_Parallel Processing_Opencl_Gpgpu - Fatal编程技术网

在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(

我是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(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);