c - 在 OpenCL 的内核中设置参数会导致错误

标签 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];
}

local_work_size=32 因为我对 32 个元素求平方。

在我的程序中,我声明了一个整数数组,其中包含要平方的元素。

int *A;
A=(int*)malloc(sizeof(int)*64);
for (i=0; i < 32; i++) {            A[i] = i;   }

platforms[i]存储平台 ID,devices[j]存储相应的设备ID。他们的类型:

cl_platform_id* platforms;
cl_device_id* devices;

创建上下文

cl_context context=clCreateContext(NULL,1,&devices[j],NULL,NULL,NULL);

接下来是命令队列

cl_command_queue cmdqueue=cmdqueue=clCreateCommandQueue(context,devices[j],NULL,&err);

接下来我创建了 2 个内存缓冲区,一个用于保存输入数据,另一个用于保存结果。

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_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

下一步获取构建信息

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_INVALID_MEM_OBJECT .

P.S.: 根据指出的错误,即在参数中使用 &Abuffer 而不是 Abuffer 并在进行必要的更改后,两者都返回 0

size_t global_item_size = 32;
size_t local_item_size = 32;

还有 ret = clEnqueueNDRangeKernel(cmdqueue, kernel, 1, NULL,&global_item_size, &local_item_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]);
                }

这将返回 buildstatus=0 并为我的 AMD GPU(运行 AMD 加速并行处理平台)和 NVIDIA GPU 转储核心,而它如果所选设备是使用 Intel(R) OpenCL 平台的 CPU,它工作得很好.

我还尝试使用以下方法获取构建日志:

cl_build_status *status=(cl_build_status *)malloc(sizeof(cl_build_status )*size);
clGetProgramBuildInfo(kernelprgrm,devices[j], CL_PROGRAM_BUILD_STATUS ,size,status,NULL);
printf("\nBuild status=%d\n",*status);

//如果不成功获取构建信息

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: Compilation started Compilation done Linking started Linking done Device build started Device build done Kernel <dataParallel> was successfully vectorized (4) Done.

最佳答案

以下是 OpenCL 1.2 规范关于将缓冲区设置为内核参数的内容:

If the argument is a memory object (buffer, image or image array), the arg_value entry will be a pointer to the appropriate buffer, image or image array object.

因此,您需要将一个指针 传递给cl_mem 对象:

ret=clSetKernelArg(kernel,0,sizeof(cl_mem),(void *) &Abuffer);

关于c - 在 OpenCL 的内核中设置参数会导致错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31159492/

相关文章:

c - clang 和 gcc 之间的行为差​​异?

linux - 相同 cpu 的不同汇编语法?

python - Theano 中归约操作的加速

c - 发送:无效参数

c -\b 和\r 在 C 中的用法

c++ - 如何以编程方式区分虚拟机中的 GPT 动态磁盘和 GPT 基本磁盘

c++ - const char* 与字符串文字的使用

c - 让从机等待来自主机的 MPI_Bcast

bash - 文件存在时运行 GNU Parallel

c - 如何浏览C源代码?