首页 > 解决方案 > clBuildProgram() 在 Mac (Catalina) 上使用 clang 总是返回 -11;clGetProgramBuildInfo() 返回空字符串

问题描述

我有一台运行 macOS Catalina (10.16.7) 的 2019 MacBook Pro,该机器配备 AMD Radeon Pro 5300M 和板载 Intel UHD 显卡。我正在尝试使用 Clang 构建一个“Hello World”OpenCL 程序(我能够很好地查询平台和设备信息),但我永远无法clBuildProgram成功完成。如果我尝试在另一台(非 mac)机器上编译和运行程序,它会编译并运行良好。

在下面的代码中,我想我正在为 CPU 获取设备,但无论我选择什么设备,我都会收到相同的错误。如果我尝试编译并运行我从 Internet 下载的其他几个“Hello World”openCL 示例,我也会遇到同样的错误。所以我认为我编译程序的方式有问题,或者我的配置有其他问题。我不知道从这里去哪里。有任何想法吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

#define MAX_NUM_DEVICES_PER_PLATFORM 128
#define MEM_SIZE 128

int main() {
    static const char source[] =
        "__kernel void hello(__global char* string)\n"
        "{\n"
        "    string[0] = 'H';  string[1] = 'e'; string[2] = 'l';  string[3] = 'l';\n"
        "    string[4] = 'o';  string[5] = ','; string[6] = ' ';  string[7] = 'W';\n"
        "    string[8] = 'o';  string[9] = 'r'; string[10] = 'l'; string[11] = 'd';\n"
        "    string[12] = '!'; string[13] = '\\0';\n"
        "}";

    // Get OpenCL device and create an OpenCL context
    cl_platform_id platforms;  cl_uint numPlatforms;
    cl_int ret = clGetPlatformIDs(1, &platforms, &numPlatforms);

    cl_uint numDevices;  cl_device_id devices[MAX_NUM_DEVICES_PER_PLATFORM];
    clGetDeviceIDs(platforms, CL_DEVICE_TYPE_ALL, MAX_NUM_DEVICES_PER_PLATFORM, devices, &numDevices);
    cl_device_id device = devices[0];

    cl_context context = clCreateContext(NULL, 1, &device, NULL, NULL, &ret);

    cl_command_queue commandQueue = clCreateCommandQueue(context, device, 0, &ret);
    cl_mem memBuffer = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * sizeof(char), NULL, NULL);

    // Build program
    size_t programSize;
    const char *src=source;
    size_t srcsize = strlen(source);
    cl_program program = clCreateProgramWithSource(context, 1, (const char**)&src, &srcsize, NULL);

    if(program == NULL) {
        fprintf(stderr, "Unable to create OpenCL program.\n");
        exit(1);
    }

    cl_int errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
    if (errNum != CL_SUCCESS) {
        fprintf(stderr, "Unable to build OpenCL program (error %i)\n", errNum);
        size_t len = 0;
        cl_int ret = CL_SUCCESS;
        ret = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &len);
        char *buffer = calloc(len, sizeof(char));
        ret = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, len, buffer, NULL);
        fprintf(stderr, "Error: %s\n", buffer);
        exit(1);
    }

    cl_kernel kernel = clCreateKernel(program, "hello", NULL);
    ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memBuffer);

    // Run the kernel
    ret = clEnqueueTask(commandQueue, kernel, 0, NULL,NULL);
     
    // Get results from memory buffer
    char string[MEM_SIZE];
    ret = clEnqueueReadBuffer(commandQueue, memBuffer, CL_TRUE, 0,
        MEM_SIZE * sizeof(char),string, 0, NULL, NULL);
    puts(string);

    return 0;
}

如果我编译并运行,我会得到以下输出:

+ clang hello.c -framework opencl -o hello
+ ./hello
Unable to build OpenCL program (error -11)
Error:

标签: cclanggpuopenclmacos-catalina

解决方案


使用 clang 或其他编译器构建主机代码与用于构建 OpenCL 内核的编译器无关。

该程序尝试为所有可用的 OpenCL 平台构建 OpenCL 内核,在这种情况下可以是 AMD GPU、Intel GPU 和 Intel CPU。我建议尝试构建一个特定的,例如:

ret = clBuildProgram(program, 1, &device_id, "-I. -Werror", NULL, NULL);

除此之外,还有很多关于 Mac 上 OpenCL 实现问题的帖子,您可能也想搜索一下。


推荐阅读