From f802340dc0c3a6befe2de44907ec8275e34a4924 Mon Sep 17 00:00:00 2001 From: yejianwu Date: Thu, 7 Dec 2017 20:40:49 +0800 Subject: [PATCH] generate opencl kernel binary from source, and create opencl program with binary --- mace/core/runtime/opencl/opencl_runtime.cc | 92 ++++++++++++++++++---- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/mace/core/runtime/opencl/opencl_runtime.cc b/mace/core/runtime/opencl/opencl_runtime.cc index 57463d3a..47020d05 100644 --- a/mace/core/runtime/opencl/opencl_runtime.cc +++ b/mace/core/runtime/opencl/opencl_runtime.cc @@ -10,26 +10,47 @@ #include "mace/core/logging.h" #include "mace/core/runtime/opencl/opencl_runtime.h" +#include + namespace mace { namespace { -bool ReadSourceFile(const std::string &filename, std::string *content) { - MACE_CHECK_NOTNULL(content); - *content = ""; - std::ifstream ifs(filename, std::ifstream::in); +bool ReadFile(const std::string &filename, std::string &content, bool binary) { + content = ""; + + std::ios_base::openmode mode = std::ios::in; + if (binary) + mode |= std::ios::binary; + + std::ifstream ifs(filename, mode); + if (!ifs.is_open()) { LOG(ERROR) << "Failed to open file " << filename; return false; } - std::string line; - while (std::getline(ifs, line)) { - *content += line; - *content += "\n"; - } + + ifs.seekg(0, std::ios::end); + content.reserve(ifs.tellg()); + ifs.seekg(0, std::ios::beg); + content.assign(std::istreambuf_iterator(ifs), + std::istreambuf_iterator()); + ifs.close(); return true; } +bool WriteFile(const std::string &filename, std::string &content, bool binary) { + std::ios_base::openmode mode = std::ios::out; + if (binary) + mode |= std::ios::binary; + std::ofstream ofs(filename, mode); + + ofs.write(content.c_str(), content.size()); + ofs.close(); + + return true; +} + } // namespace bool OpenCLRuntime::enable_profiling_ = false; @@ -159,13 +180,31 @@ void OpenCLRuntime::BuildProgram(const std::string &program_file_name, cl::Program *program) { MACE_CHECK_NOTNULL(program); - cl::Program::Sources sources; - std::string filename = kernel_path_ + program_file_name; - std::string kernel_source; - MACE_CHECK(ReadSourceFile(filename, &kernel_source)); - sources.push_back({kernel_source.c_str(), kernel_source.length()}); + std::string source_filename = kernel_path_ + program_file_name; + std::string binary_filename = source_filename + "bin"; + + if (std::ifstream(binary_filename).is_open()) { + VLOG(1) << "Create program with binary: " << binary_filename; + std::string kernel_binary; + MACE_CHECK(ReadFile(binary_filename, kernel_binary, true)); + + std::vector binaries(kernel_binary.begin(), kernel_binary.end()); + + *program = cl::Program(this->context(), {device()}, {binaries}); + + } else if (std::ifstream(source_filename).is_open()) { + VLOG(1) << "Create program with source: " << source_filename; + std::string kernel_source; + MACE_CHECK(ReadFile(source_filename, kernel_source, false)); - *program = cl::Program(this->context(), sources); + cl::Program::Sources sources; + sources.push_back({kernel_source.c_str(), kernel_source.length()}); + + *program = cl::Program(this->context(), sources); + } else { + LOG(ERROR) << "Failed to open kernel file " << binary_filename << " and " + << source_filename; + } std::string build_options_str = build_options + " -Werror -cl-mad-enable -cl-fast-relaxed-math -I" + kernel_path_; // TODO(heliangliang) -cl-unsafe-math-optimizations -cl-fast-relaxed-math @@ -179,6 +218,29 @@ void OpenCLRuntime::BuildProgram(const std::string &program_file_name, } LOG(FATAL) << "Build program failed: " << ret; } + + if (!std::ifstream(binary_filename).is_open()) { + size_t deviceListSize = 1; + size_t *programBinarySizes = new size_t[deviceListSize]; + clGetProgramInfo((*program)(), + CL_PROGRAM_BINARY_SIZES, + sizeof(size_t) * deviceListSize, + programBinarySizes, + NULL); + unsigned char **programBinaries = new unsigned char *[deviceListSize]; + for(cl_uint i = 0; i < deviceListSize; ++i) + programBinaries[i] = new unsigned char[programBinarySizes[i]]; + + clGetProgramInfo((*program)(), + CL_PROGRAM_BINARIES, + sizeof(unsigned char *) * deviceListSize, + programBinaries, + NULL); + std::string content(reinterpret_cast(programBinaries[0]), + programBinarySizes[0]); + + WriteFile(binary_filename, content, true); + } } cl::Kernel OpenCLRuntime::BuildKernel(const std::string &program_name, -- GitLab