gpt4 book ai didi

c++ - OpenCL 从二进制加载程序

转载 作者:行者123 更新时间:2023-11-28 04:27:31 25 4
gpt4 key购买 nike

我在 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),但未显示正确的输入结果。它像这样显示不断变化的垃圾值


结果:
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 文件有什么不同吗?


编辑:

我是如何创建二进制文件的

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;
}

最佳答案

根据 OpenCL Specification s5.6.2 "Building Program Executables",即使对于 clCreateProgramWithBinary 创建的程序,也必须调用

clBuildProgram :

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

这样做的原因是“设备二进制文件”不是目标设备的完全编译/链接的机器代码:它可以是某种形式的中间表示(例如 LLVM IR),需要进一步编译。

关于c++ - OpenCL 从二进制加载程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53938591/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com