-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[OpenCL/GPU] Kernel binary caching @open sesame 04/04 09:22 #2503
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ | |
|
||
#include "opencl_program.h" | ||
|
||
#include <cstring> | ||
#include <fstream> | ||
#include <string> | ||
|
||
#include "opencl_loader.h" | ||
|
@@ -29,8 +31,8 @@ namespace nntrainer::opencl { | |
* @return true if successful or false otherwise | ||
*/ | ||
bool Program::BuildProgram(cl_device_id device_id, | ||
const std::string &compiler_options) { | ||
|
||
const std::string &compiler_options, | ||
bool binaryCreated) { | ||
// clBuildProgram returns NULL with error code if fails | ||
const int error_code = clBuildProgram( | ||
program_, 0, nullptr, compiler_options.c_str(), nullptr, nullptr); | ||
|
@@ -41,6 +43,101 @@ bool Program::BuildProgram(cl_device_id device_id, | |
return false; | ||
} | ||
|
||
// saving kernel binary | ||
if (!binaryCreated) | ||
return GetProgramInfo(device_id); | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* @brief Utility to get program info and save kernel binaries | ||
* | ||
* @param device_id OpenCL device id | ||
* @return true if successful or false otherwise | ||
*/ | ||
bool Program::GetProgramInfo(cl_device_id device_id) { | ||
// since only one GPU is being used | ||
unsigned int num_devices = 1; | ||
|
||
cl_int error_code = CL_SUCCESS; | ||
|
||
// Read the binary size | ||
size_t binaries_size[num_devices]; | ||
error_code = | ||
clGetProgramInfo(program_, CL_PROGRAM_BINARY_SIZES, | ||
sizeof(size_t) * num_devices, binaries_size, nullptr); | ||
|
||
if (error_code != CL_SUCCESS) { | ||
ml_loge("Failed to get program binary size. OpenCL error code: %d. %s", | ||
error_code, | ||
(GetProgramBuildInfo(device_id, CL_PROGRAM_BUILD_LOG)).c_str()); | ||
return false; | ||
} | ||
|
||
// Read the kernel name size | ||
size_t kernel_names_size; | ||
error_code = clGetProgramInfo(program_, CL_PROGRAM_KERNEL_NAMES, 0, nullptr, | ||
&kernel_names_size); | ||
|
||
if (error_code != CL_SUCCESS) { | ||
ml_loge("Failed to get program kernel name size. OpenCL error code: %d. %s", | ||
error_code, | ||
(GetProgramBuildInfo(device_id, CL_PROGRAM_BUILD_LOG)).c_str()); | ||
return false; | ||
} | ||
|
||
// getting the kernel names | ||
char kernel_names[kernel_names_size]; | ||
error_code = clGetProgramInfo(program_, CL_PROGRAM_KERNEL_NAMES, | ||
kernel_names_size, kernel_names, nullptr); | ||
|
||
if (error_code != CL_SUCCESS) { | ||
ml_loge("Failed to get program kernel names. OpenCL error code: %d. %s", | ||
error_code, | ||
(GetProgramBuildInfo(device_id, CL_PROGRAM_BUILD_LOG)).c_str()); | ||
return false; | ||
} else { | ||
ml_logi("Saving kernel binary for: %s", std::string(kernel_names).c_str()); | ||
} | ||
|
||
// Read the binary | ||
size_t binaries_ptr_alloc_size = sizeof(unsigned char *) * num_devices; | ||
unsigned char *binaries_ptr[num_devices]; | ||
|
||
for (unsigned int i = 0; i < num_devices; ++i) { | ||
binaries_ptr[i] = new unsigned char[binaries_size[i]]; | ||
} | ||
|
||
error_code = clGetProgramInfo(program_, CL_PROGRAM_BINARIES, | ||
binaries_ptr_alloc_size, binaries_ptr, nullptr); | ||
|
||
if (error_code != CL_SUCCESS) { | ||
ml_loge("Failed to get program binary data. OpenCL error code: %d. %s", | ||
error_code, | ||
(GetProgramBuildInfo(device_id, CL_PROGRAM_BUILD_LOG)).c_str()); | ||
|
||
// cleanup | ||
for (unsigned int i = 0; i < num_devices; ++i) { | ||
delete[] binaries_ptr[i]; | ||
} | ||
return false; | ||
s-debadri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
// Write the binary to file | ||
// All kernels in the program will be saved in the binary file | ||
for (unsigned int i = 0; i < num_devices; ++i) { | ||
std::ofstream fs(std::string(kernel_names) + "_kernel.bin", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It needs to get a parameter save path like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorporated opencl-kernel-path pre-processor directive in latest commit |
||
std::ios::out | std::ios::binary | std::ios::app); | ||
fs.write((char *)binaries_ptr[i], binaries_size[i]); | ||
fs.close(); | ||
} | ||
|
||
// cleanup | ||
for (unsigned int i = 0; i < num_devices; ++i) { | ||
delete[] binaries_ptr[i]; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
|
@@ -103,6 +200,41 @@ bool Program::CreateCLProgram(const cl_context &context, | |
return BuildProgram(device_id, compiler_options); | ||
} | ||
|
||
/** | ||
* @brief Create OpenCL program from pre compiled binary | ||
* | ||
* @param context OpenCL context | ||
* @param device_id OpenCL device id | ||
* @param size binary file size | ||
* @param binary data saved as binary | ||
* @param binary_name name of binary file for logging | ||
* @param compiler_options string compiler options | ||
* @return true if successful or false otherwise | ||
*/ | ||
bool Program::CreateCLProgramWithBinary(const cl_context &context, | ||
const cl_device_id &device_id, | ||
size_t size, unsigned char *binary, | ||
std::string binary_name, | ||
const std::string &compiler_options) { | ||
|
||
int error_code; | ||
const cl_device_id device_list[] = {device_id}; | ||
const size_t lengths[] = {size}; | ||
const unsigned char *binaries[] = {binary}; | ||
|
||
program_ = clCreateProgramWithBinary(context, 1, device_list, lengths, | ||
binaries, NULL, &error_code); | ||
if (!program_ || error_code != CL_SUCCESS) { | ||
ml_loge("Failed to create compute program. OpenCL error code: %d", | ||
error_code); | ||
return false; | ||
} | ||
|
||
ml_logi("Loaded program from binary for: %s", binary_name.c_str()); | ||
|
||
return BuildProgram(device_id, compiler_options, true); | ||
} | ||
|
||
/** | ||
* @brief Get the Program object | ||
* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to add a comment for
@param binaryCreated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in latest commit.