OpenCL load program from binary

喜欢而已 提交于 2019-12-11 15:38:57

问题


I have the following very simple kernel in OpenCL

void kernel simple_add(global const int* A, global const int* B, global int* C){
    C[get_global_id(0)]=A[get_global_id(0)]+B[get_global_id(0)];
};

I created a C++ program to load the kernel from a binary created from its source. The binary loads correctly (CL_SUCCESS), but does not display the correct result for the input. It displays changing garbage values like so

result: 538976310 538976288 538976288 538976288 538976288 790634528 796160111 1702129257 1886334828 1818455653

inline cl::Program CreateProgramFromBinary(cl::Context context,const std::vector<cl::Device> devices, const char* fileName)
{
    std::ifstream file(fileName,  std::ios::binary | std::ios::in | std::ios::ate);

    uint32_t size = file.tellg();
    file.seekg(0, std::ios::beg);
    char* buffer = new char[size];
    file.read(buffer, size);
    file.close();
    cl::Program::Binaries bin{{buffer, size}};

    std::vector<cl_int> binaryStatus;
    cl_int err = 0;
    cl::Program program = cl::Program{context, devices, bin, &binaryStatus, &err};

    if(err != CL_SUCCESS) {
       std::cout<<" Error loading"<< err<<  "\n";
        exit(1);
    }
    for (std::vector<cl_int>::const_iterator bE = binaryStatus.begin(); bE != binaryStatus.end(); bE++) {
        std::cout<< *bE <<std::endl;
    }
    std::cout<<"No Error loading"<< err<<  "\n";
    delete[] buffer;
    return program;
}

int main(int argc, char** argv)
{
    std::vector<cl::Device> devices= loadDevices();
    cl::Context context{devices};

    std::cout << "Save program binary for future run..." << std::endl;
    //cl::Program program = CreateBinaryFromProgram(context, devices, "HelloWorld.cl", "HelloWorld.cl.bin");
    //CreateBinaryFromProgram(context, devices, "HelloWorld.cl", "HelloWorld.cl.bin");


    std::cout << "Reading from binary..." << std::endl;
    cl::Program program = CreateProgramFromBinary(context, devices, "HelloWorld.cl.bin");

    std::cout << "Running Program..." << std::endl;
    cl::Buffer buffer_A(context,CL_MEM_READ_WRITE,sizeof(int)*10);
    cl::Buffer buffer_B(context,CL_MEM_READ_WRITE,sizeof(int)*10);
    cl::Buffer buffer_C(context,CL_MEM_READ_WRITE,sizeof(int)*10);

    int A[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int B[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    //create queue to which we will push commands for the device.
    cl::CommandQueue queue(context,devices[0]);

    //write arrays A and B to the device
    queue.enqueueWriteBuffer(buffer_A,CL_TRUE,0,sizeof(int)*10,A);
    queue.enqueueWriteBuffer(buffer_B,CL_TRUE,0,sizeof(int)*10,B);


    //run the kernel
    cl::Kernel kernel_add=cl::Kernel(program,"simple_add");
    kernel_add.setArg(0,buffer_A);
    kernel_add.setArg(1,buffer_B);
    kernel_add.setArg(2,buffer_C);
    queue.enqueueNDRangeKernel(kernel_add,cl::NullRange,cl::NDRange(10),cl::NullRange);
    queue.finish();

    int C[10];
    //read result C from the device to array C
    queue.enqueueReadBuffer(buffer_C,CL_TRUE,0,sizeof(int)*10,C);

    std::cout<<" result: \n";
    for(int i=0;i<10;i++)
        std::cout<<C[i]<<" ";
    std::cout << "\n";
    return 0;
}

Loading this program directly from the CL file however, results in the correct output of the program. Is the binary I've loaded somehow different from the CL file?


EDIT:

How I created the Binary

inline cl::Program CreateBinaryFromProgram(const cl::Context context,const std::vector<cl::Device> devices, const char* readFileName, const char* writeFileName)
{
    std::ifstream file(readFileName, std::ios::binary| std::ios::ate | std::ios::in);

    uint32_t size = file.tellg();
    file.seekg(0, std::ios::beg);
    char* buffer = new char[size];

    file.read(buffer, size);
    file.close();

    cl::Program::Sources sources;

    // kernel calculates for each element C=A+B
    std::string kernel_code(buffer);
    sources.push_back({kernel_code.c_str(),kernel_code.length()});
    cl::Program program{context,sources};
    if(program.build(devices)!=CL_SUCCESS){
       std::cout<<" Error building: "<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0])<<"\n";
        exit(1);
    }
    std::vector<size_t> output_sizes = program.getInfo<CL_PROGRAM_BINARY_SIZES>();
    std::vector<char*> output = program.getInfo<CL_PROGRAM_BINARIES>();
    std::cout << sizeof(output[0]) << std::endl;
    std::cout << output_sizes[0] << std::endl;

    const std::vector<unsigned long> binSizes = program.getInfo<CL_PROGRAM_BINARY_SIZES>();
    std::vector<char> binData (std::accumulate(binSizes.begin(),binSizes.end(),0));
    char* binChunk = &binData[0] ;


    //A list of pointers to the binary data    
    std::vector<char*> binaries;
    for(unsigned int i = 0; i<binSizes.size(); ++i) {
         binaries.push_back(binChunk) ;
         binChunk += binSizes[i] ;
    }

    program.getInfo(CL_PROGRAM_BINARIES , &binaries[0] ) ;
    std::ofstream binaryfile(writeFileName, std::ios::binary);
    for (unsigned int i = 0; i < binaries.size(); ++i)
        binaryfile.write(binaries[i], binSizes[i]);
    delete[] buffer;
    return program;
}

回答1:


clBuildProgram must be called even for a program created by clCreateProgramWithBinary, according to the OpenCL Specification s5.6.2 "Building Program Executables":

OpenCL allows program executables to be built using the source or the binary. clBuildProgram must be called for program created using either clCreateProgramWithSource or clCreateProgramWithBinary to build the program executable for one or more devices associated with program. If program is created with clCreateProgramWithBinary, then the program binary must be an executable binary (not a compiled binary or library).

The reason for this is that a "device binary" is not necessary a fully compiled/linked machine code for a target device: it can be an intermediate representation in some form (e.g. LLVM IR), that requires further compilation.



来源:https://stackoverflow.com/questions/53938591/opencl-load-program-from-binary

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!