OpenCL从二进制文件加载程序 [英] OpenCL load program from binary
问题描述
我在OpenCL中有以下非常简单的内核
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)];
};
我创建了一个C ++程序,用于从源代码创建的二进制文件中加载内核。二进制文件正确加载(CL_SUCCESS),但没有为输入显示正确的结果。它将显示变化的垃圾值,如下所示:
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
结果:
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;
}
直接从CL文件中加载此程序会导致正确的输出该程序。我加载的二进制文件与CL文件是否有所不同?
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?
编辑:
我如何创建二进制文件
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;
}
推荐答案
根据 clCreateProgramWithBinary
创建的程序,也必须调用clBuildProgram 。注册表/OpenCL/specs/opencl-1.2.pdf rel = nofollow noreferrer> OpenCL规范s5.6.2构建程序可执行文件 :
clBuildProgram
must be called even for a program created by clCreateProgramWithBinary
, according to the OpenCL Specification s5.6.2 "Building Program Executables":
OpenCL允许使用源代码或二进制文件来构建程序可执行文件。对于使用
clCreateProgramWithSource
或clCreateProgramWithBinary
clBuildProgram >为与程序关联的一个或多个设备构建程序可执行文件。如果使用clCreateProgramWithBinary
创建程序,则该程序二进制文件必须是可执行二进制文件(而不是编译的二进制文件或库)。
OpenCL allows program executables to be built using the source or the binary.
clBuildProgram
must be called for program created using eitherclCreateProgramWithSource
orclCreateProgramWithBinary
to build the program executable for one or more devices associated with program. If program is created withclCreateProgramWithBinary
, then the program binary must be an executable binary (not a compiled binary or library).
其原因是设备二进制文件不一定是目标设备的完全编译/链接的机器代码:它可以是某种形式的中间表示(例如LLVM IR) ),则需要进一步编译。
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.
这篇关于OpenCL从二进制文件加载程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!