openCL无法同时为CPU和GPU保存编译的二进制文件

openCL无法同时为CPU和GPU保存编译的二进制文件,opencl,gpu,cpu,binaryfiles,Opencl,Gpu,Cpu,Binaryfiles,因此,我正在编写一个在CPU+GPU上运行的openCL程序,在使用clCreateProgramWithSource()创建程序后,我目前正在尝试保存/缓存二进制文件。我使用CL_DEVICE_TYPE_ALL创建我的clContext和clProgram,并使用这些规范构建源代码 然后,我将二进制文件存储到磁盘(每个设备有一个二进制文件),以便在后续启动时,我的程序自动调用clBuildProgramWithBinary 问题是,如果我将二进制文件保存到使用设置CL_DEVICE_TYPE_

因此,我正在编写一个在CPU+GPU上运行的openCL程序,在使用clCreateProgramWithSource()创建程序后,我目前正在尝试保存/缓存二进制文件。我使用CL_DEVICE_TYPE_ALL创建我的clContext和clProgram,并使用这些规范构建源代码

然后,我将二进制文件存储到磁盘(每个设备有一个二进制文件),以便在后续启动时,我的程序自动调用clBuildProgramWithBinary

问题是,如果我将二进制文件保存到使用设置CL_DEVICE_TYPE_ALL创建的磁盘上,CPU的二进制文件就会损坏,并且clBuildProgramWithBinary会抛出一个错误

为了将所有二进制文件正确保存到磁盘,我必须编辑代码,首先使用CL_DEVICE_TYPE_CPU运行,并单独保存CPU二进制文件,然后再次编辑代码,使用CL_DEVICE_TYPE_GPU运行,保存GPU二进制文件,最后将其切换回CL_DEVICE_TYPE_all。如果我这样做,clBuildProgramWithBinary能够准确地为每种设备类型构建二进制文件并执行我的程序

所以这只是openCL的一个怪癖,我不能同时为GPU和CPU构建二进制文件吗?还是我做得不对

我的代码基于这里发现的二进制保存的实现:经过适当的修改以处理多个设备

下面是我的代码的一些部分:

/*----Initial setup of platform, context and devices---*/
cl_int err, deviceCount;
cl_device_id *devices;
cl_platform_id platform;
cl_context context;
cl_program program;
err = clGetPlatformIDs(1, &platform, NULL);
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &deviceCount);
devices = new cl_device_id[deviceCount];
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, deviceCount, devices, NULL);
context = clCreateContext(NULL, deviceCount, devices, NULL, NULL, &err);


/*---Build Program---*/
int numFiles = 2;
const char *sourceFiles[] =
{
     "File1.cl",
     "File2.cl",
};


char *sourceStrings[numFiles];
for(int i = 0; i < numFiles; i++)
{
    sourceStrings[i] = ReadFile(sourceFiles[i]);
}

/*---Create the compute program from the source buffer---*/
program = clCreateProgramWithSource(context, numFiles, (const char **)sourceStrings, NULL, &err);

/*---Build the program executable---*/
err = clBuildProgram(program, deviceCount, devices, NULL, NULL, NULL);


/*----Save binary to disk---*/
//Determine the size of each program binary
size_t *programBinarySizes = new size_t[deviceCount];
err = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t) * deviceCount, programBinarySizes, NULL);

if(err != CL_SUCCESS)
{
    delete [] devices;
    delete [] programBinarySizes;
    return false;
}

unsigned char **programBinaries = new unsigned char*[deviceCount];
for(cl_uint i = 0; i < deviceCount; i++)
{
    programBinaries[i] = new unsigned char[programBinarySizes[i]];
}

//Get all of the program binaries
err = clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(unsigned char *) * deviceCount, programBinaries, NULL);

if (err != CL_SUCCESS)
{        
    delete [] devices;
    delete [] programBinarySizes;
    for (cl_uint i = 0; i < deviceCount; i++)
    {
        delete [] programBinaries[i];
    }
    delete [] programBinaries;
}

//Store the binaries
for(cl_uint i = 0; i < deviceCount; i++)
{
    // Store the binary for all devices
    std::string currFile = binaryFile + to_string(i) + ".txt";
    FILE *fp = fopen(currFile.c_str(), "wb");
    fwrite(programBinaries[i], 1, programBinarySizes[i], fp);
    fclose(fp);
}

// Cleanup
delete [] programBinarySizes;
for (cl_uint i = 0; i < deviceCount; i++)
{
    delete [] programBinaries[i];
}
delete [] programBinaries;
/*——平台、上下文和设备的初始设置---*/
cl_int err,设备计数;
cl_设备\u id*设备;
cl_平台\u id平台;
语境;
CLU计划;
err=clGetPlatformIDs(1,&platform,NULL);
err=CLGetDeviceID(平台、CL\U设备类型\U ALL、0、NULL和设备计数);
设备=新的cl_设备id[设备计数];
err=CLGetDeviceID(平台、CL\U设备类型、设备计数、设备、空);
context=clCreateContext(NULL、deviceCount、devices、NULL、NULL和err);
/*---构建程序---*/
int numFiles=2;
常量字符*源文件[]=
{
“File1.cl”,
“File2.cl”,
};
char*sourceStrings[numFiles];
对于(int i=0;i
然后在下一步中,使用调用此函数来循环我的代码,以从二进制文件创建程序:

unsigned char **programBinaries = new unsigned char *[deviceCount];
size_t sizes[deviceCount];
for(int i = 0; i < deviceCount; i++)
{
    string currFile = binaryFile + to_string(i) + ".txt";
    FILE *fp = fopen(currFile.c_str(), "rb");
    if(!fp) return NULL;

    size_t binarySize;
    fseek(fp, 0, SEEK_END);
    binarySize = ftell(fp);
    sizes[i] = binarySize;
    rewind(fp);

    programBinaries[i] = new unsigned char[binarySize];
    fread(programBinaries[i], 1, binarySize, fp);
    fclose(fp);
}

cl_int errNum = 0;
cl_program program;
cl_int binaryStatus;


program = clCreateProgramWithBinary(context,
                                    deviceCount,
                                    devices,
                                    sizes,
                                    (const unsigned char **)programBinaries,
                                    &binaryStatus,
                                    &errNum);



delete [] programBinaries;


errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
unsigned char**programmabinaries=新的unsigned char*[deviceCount];
大小[设备计数];
for(int i=0;i
我有一个rmbp,它在一个苹果平台上有三台设备。我在上面运行了你的代码,遇到了同样的问题。实际上我不知道解决方案,但我可以给你一些调试提示

  • 不要使用ftell计算常规文件的大小,请参阅原因
  • 我对您的代码段进行了如下修改:

        #include <sys/stat.h>
        unsigned char **programBinaries = new unsigned char *[deviceCount];
        size_t sizes[deviceCount];
        int fd;
        struct stat st;
        for(cl_uint i = 0; i < deviceCount; i++)
        {
            string currFile = binaryFile + to_string(i) + ".txt";
            fd = open(currFile.c_str(), O_RDONLY);
            if (fd == -1) {
                return -1;
            }
    
            if ((fstat(fd, &st) != 0) || (!S_ISREG(st.st_mode))) {
                return -2;
            }
    
            size_t binarySize;            
            FILE *fp = fdopen(fd, "rb");
            if (fseeko(fp, 0 , SEEK_END) != 0) {
                return -3;
            }
            binarySize = ftello(fp);
            cout << "device " << i << ": " << binarySize << endl;
            sizes[i] = binarySize;
            rewind(fp);
    
            programBinaries[i] = new unsigned char[binarySize];
            fread(programBinaries[i], 1, binarySize, fp);
            fclose(fp);
            close(fd);
        }
    
    第一行表示第一个二进制程序(用于CPU)已成功加载-第二行中的42对应于
    CL\u INVALID\u BINARY
    ,这意味着无法加载二进制程序

  • 我还试图从程序中检索构建选项,但什么也没有得到

    //set device_id to 0,1,3...
    cl_uint device_id = 0;
    cl_build_status status;
    // Determine the reason for the error
    char buildOptions[16384];
    char buildLog[16384];
    clGetProgramBuildInfo(program, devices[device_id], CL_PROGRAM_BUILD_STATUS,
                          sizeof(cl_build_status), &status, NULL);
    std::cout << "status: " << status << endl;
    
    clGetProgramBuildInfo(program, devices[device_id], CL_PROGRAM_BUILD_OPTIONS,
                          sizeof(buildOptions), buildOptions, NULL);
    std::cout << "build options: " << endl;
    std::cout << buildOptions;
    
    clGetProgramBuildInfo(program, devices[device_id], CL_PROGRAM_BUILD_LOG,
                          sizeof(buildLog), buildLog, NULL);
    std::cout << "build log: " << endl;
    std::cout << buildLog;
    
    //将设备id设置为0,1,3。。。
    cl_单元设备id=0;
    cl_建造_状态状态;
    //确定错误的原因
    字符构建选项[16384];
    char buildLog[16384];
    clGetProgramBuildInfo(程序、设备[设备id]、CL_程序构建状态、,
    sizeof(cl_build_status),&status,NULL);
    std::您是否可以检查(或提供)CPU和GPU的示例二进制文件(例如,只是为了一个简单的
    
    device: 0: 0
    device: 1: -42
    
    //set device_id to 0,1,3...
    cl_uint device_id = 0;
    cl_build_status status;
    // Determine the reason for the error
    char buildOptions[16384];
    char buildLog[16384];
    clGetProgramBuildInfo(program, devices[device_id], CL_PROGRAM_BUILD_STATUS,
                          sizeof(cl_build_status), &status, NULL);
    std::cout << "status: " << status << endl;
    
    clGetProgramBuildInfo(program, devices[device_id], CL_PROGRAM_BUILD_OPTIONS,
                          sizeof(buildOptions), buildOptions, NULL);
    std::cout << "build options: " << endl;
    std::cout << buildOptions;
    
    clGetProgramBuildInfo(program, devices[device_id], CL_PROGRAM_BUILD_LOG,
                          sizeof(buildLog), buildLog, NULL);
    std::cout << "build log: " << endl;
    std::cout << buildLog;