提交 c5de2c92 编写于 作者: Y yejianwu

format kernel binary code

上级 c76f7825
...@@ -31,8 +31,8 @@ bool ReadFile(const std::string &filename, std::string &content, bool binary) { ...@@ -31,8 +31,8 @@ bool ReadFile(const std::string &filename, std::string &content, bool binary) {
} }
ifs.seekg(0, std::ios::end); ifs.seekg(0, std::ios::end);
size_t filesize = ifs.tellg(); const size_t filesize = ifs.tellg();
if ((filesize / 1024.0 / 1024.0) > 10) { if (filesize > 10 * 1024 * 1024) {
LOG(ERROR) << "Filesize overflow 10MB"; LOG(ERROR) << "Filesize overflow 10MB";
return false; return false;
} }
...@@ -42,10 +42,16 @@ bool ReadFile(const std::string &filename, std::string &content, bool binary) { ...@@ -42,10 +42,16 @@ bool ReadFile(const std::string &filename, std::string &content, bool binary) {
std::istreambuf_iterator<char>()); std::istreambuf_iterator<char>());
ifs.close(); ifs.close();
if (ifs.fail()) {
LOG(ERROR) << "Failed to read from file " << filename;
return false;
}
return true; return true;
} }
bool WriteFile(const std::string &filename, std::string &content, bool binary) { bool WriteFile(const std::string &filename, const std::string &content,
bool binary) {
std::ios_base::openmode mode = std::ios::out; std::ios_base::openmode mode = std::ios::out;
if (binary) { if (binary) {
mode |= std::ios::binary; mode |= std::ios::binary;
...@@ -54,14 +60,18 @@ bool WriteFile(const std::string &filename, std::string &content, bool binary) { ...@@ -54,14 +60,18 @@ bool WriteFile(const std::string &filename, std::string &content, bool binary) {
ofs.write(content.c_str(), content.size()); ofs.write(content.c_str(), content.size());
ofs.close(); ofs.close();
if (ofs.fail()) {
LOG(ERROR) << "Failed to write to file " << filename;
return false;
}
return true; return true;
} }
} // namespace } // namespace
bool OpenCLRuntime::enable_profiling_ = false; bool OpenCLRuntime::enable_profiling_ = false;
std::unique_ptr<cl::Event> OpenCLRuntime::profiling_ev_ = NULL; std::unique_ptr<cl::Event> OpenCLRuntime::profiling_ev_ = nullptr;
OpenCLRuntime *OpenCLRuntime::Get() { OpenCLRuntime *OpenCLRuntime::Get() {
static std::once_flag init_once; static std::once_flag init_once;
...@@ -125,13 +135,9 @@ OpenCLRuntime *OpenCLRuntime::Get() { ...@@ -125,13 +135,9 @@ OpenCLRuntime *OpenCLRuntime::Get() {
return instance; return instance;
} }
void OpenCLRuntime::EnableProfiling() { void OpenCLRuntime::EnableProfiling() { enable_profiling_ = true; }
enable_profiling_ = true;
}
cl::Event* OpenCLRuntime::GetDefaultEvent() { cl::Event *OpenCLRuntime::GetDefaultEvent() { return profiling_ev_.get(); }
return profiling_ev_.get();
}
cl_ulong OpenCLRuntime::GetEventProfilingStartInfo() { cl_ulong OpenCLRuntime::GetEventProfilingStartInfo() {
MACE_CHECK(profiling_ev_, "is NULL, should enable profiling first."); MACE_CHECK(profiling_ev_, "is NULL, should enable profiling first.");
...@@ -143,8 +149,7 @@ cl_ulong OpenCLRuntime::GetEventProfilingEndInfo() { ...@@ -143,8 +149,7 @@ cl_ulong OpenCLRuntime::GetEventProfilingEndInfo() {
return profiling_ev_->getProfilingInfo<CL_PROFILING_COMMAND_END>(); return profiling_ev_->getProfilingInfo<CL_PROFILING_COMMAND_END>();
} }
OpenCLRuntime::OpenCLRuntime(cl::Context context, OpenCLRuntime::OpenCLRuntime(cl::Context context, cl::Device device,
cl::Device device,
cl::CommandQueue command_queue) cl::CommandQueue command_queue)
: context_(context), device_(device), command_queue_(command_queue) { : context_(context), device_(device), command_queue_(command_queue) {
const char *kernel_path = getenv("MACE_KERNEL_PATH"); const char *kernel_path = getenv("MACE_KERNEL_PATH");
...@@ -165,60 +170,51 @@ cl::Program &OpenCLRuntime::program() { ...@@ -165,60 +170,51 @@ cl::Program &OpenCLRuntime::program() {
} }
// TODO(heliangliang) Support binary format // TODO(heliangliang) Support binary format
const std::map<std::string, std::string> const std::map<std::string, std::string> OpenCLRuntime::program_map_ = {
OpenCLRuntime::program_map_ = { {"addn", "addn.cl"},
{"addn", "addn.cl"}, {"batch_norm", "batch_norm.cl"},
{"batch_norm", "batch_norm.cl"}, {"bias_add", "bias_add.cl"},
{"bias_add", "bias_add.cl"}, {"buffer_to_image", "buffer_to_image.cl"},
{"buffer_to_image", "buffer_to_image.cl"}, {"conv_2d", "conv_2d.cl"},
{"conv_2d", "conv_2d.cl"}, {"conv_2d_1x1", "conv_2d_1x1.cl"},
{"conv_2d_1x1", "conv_2d_1x1.cl"}, {"conv_2d_3x3", "conv_2d_3x3.cl"},
{"conv_2d_3x3", "conv_2d_3x3.cl"}, {"depthwise_conv_3x3", "depthwise_conv_3x3.cl"},
{"depthwise_conv_3x3", "depthwise_conv_3x3.cl"}, {"pooling", "pooling.cl"},
{"pooling", "pooling.cl"}, {"relu", "relu.cl"},
{"relu", "relu.cl"}, {"concat", "concat.cl"},
{"concat", "concat.cl"}, {"resize_bilinear", "resize_bilinear.cl"},
{"resize_bilinear", "resize_bilinear.cl"}, {"space_to_batch", "space_to_batch.cl"},
{"space_to_batch", "space_to_batch.cl"},
}; };
void OpenCLRuntime::GenerateCLBinaryFilename(std::string &filename) { std::string
while (true) { OpenCLRuntime::GenerateCLBinaryFilenamePrefix(const std::string &filename_msg) {
size_t pos = filename.find(" -D"); std::string filename_prefix = filename_msg;
if (pos == std::string::npos) { for (auto it = filename_prefix.begin(); it != filename_prefix.end(); ++it) {
break; if (*it == ' ' || *it == '-' || *it == '=') {
} *it = '_';
filename.replace(pos, 3, "__");
}
while (true) {
size_t pos = filename.find("=");
if (pos == std::string::npos) {
break;
} }
filename.replace(pos, 1, "_");
} }
return filename_prefix;
filename += ".bin";
} }
void OpenCLRuntime::BuildProgram(const std::string &program_file_name, void OpenCLRuntime::BuildProgram(const std::string &program_file_name,
const std::string &binary_file_name, const std::string &binary_file_name_prefix,
const std::string &build_options, const std::string &build_options,
cl::Program *program) { cl::Program *program) {
MACE_CHECK_NOTNULL(program); MACE_CHECK_NOTNULL(program);
std::string source_filename = kernel_path_ + program_file_name; std::string source_filename = kernel_path_ + program_file_name;
std::string binary_filename = kernel_path_ + binary_file_name; std::string binary_filename = kernel_path_ + binary_file_name_prefix + ".bin";
// Create program // Create program
if (std::ifstream(binary_filename).is_open()) { bool is_binary_filename_exist = std::ifstream(binary_filename).is_open();
if (is_binary_filename_exist) {
VLOG(1) << "Create program with binary: " << binary_filename; VLOG(1) << "Create program with binary: " << binary_filename;
std::string kernel_binary; std::string kernel_binary;
MACE_CHECK(ReadFile(binary_filename, kernel_binary, true)); MACE_CHECK(ReadFile(binary_filename, kernel_binary, true));
std::vector<unsigned char> binaries( std::vector<unsigned char> binaries(kernel_binary.begin(),
kernel_binary.begin(), kernel_binary.end()); kernel_binary.end());
*program = cl::Program(this->context(), {device()}, {binaries}); *program = cl::Program(this->context(), {device()}, {binaries});
...@@ -233,13 +229,14 @@ void OpenCLRuntime::BuildProgram(const std::string &program_file_name, ...@@ -233,13 +229,14 @@ void OpenCLRuntime::BuildProgram(const std::string &program_file_name,
*program = cl::Program(this->context(), sources); *program = cl::Program(this->context(), sources);
} else { } else {
LOG(ERROR) << "Failed to open kernel file " << binary_filename << " and " LOG(FATAL) << "Failed to open kernel file " << binary_filename << " and "
<< source_filename; << source_filename;
} }
// Build program // Build program
std::string build_options_str = build_options + std::string build_options_str =
" -Werror -cl-mad-enable -cl-fast-relaxed-math -I" + kernel_path_; build_options + " -Werror -cl-mad-enable -cl-fast-relaxed-math -I" +
kernel_path_;
// TODO(heliangliang) -cl-unsafe-math-optimizations -cl-fast-relaxed-math // TODO(heliangliang) -cl-unsafe-math-optimizations -cl-fast-relaxed-math
cl_int ret = program->build({device()}, build_options_str.c_str()); cl_int ret = program->build({device()}, build_options_str.c_str());
if (ret != CL_SUCCESS) { if (ret != CL_SUCCESS) {
...@@ -253,34 +250,32 @@ void OpenCLRuntime::BuildProgram(const std::string &program_file_name, ...@@ -253,34 +250,32 @@ void OpenCLRuntime::BuildProgram(const std::string &program_file_name,
} }
// Write binary if necessary // Write binary if necessary
if (!std::ifstream(binary_filename).is_open()) { if (!is_binary_filename_exist) {
size_t deviceListSize = 1; size_t deviceListSize = 1;
size_t *programBinarySizes = new size_t[deviceListSize]; size_t *programBinarySizes = new size_t[deviceListSize];
clGetProgramInfo((*program)(), cl_int err = clGetProgramInfo((*program)(), CL_PROGRAM_BINARY_SIZES,
CL_PROGRAM_BINARY_SIZES, sizeof(size_t) * deviceListSize,
sizeof(size_t) * deviceListSize, programBinarySizes, nullptr);
programBinarySizes, MACE_CHECK(err == CL_SUCCESS) << "Error code: " << err;
NULL);
unsigned char **programBinaries = new unsigned char *[deviceListSize]; unsigned char **programBinaries = new unsigned char *[deviceListSize];
for(cl_uint i = 0; i < deviceListSize; ++i) for (cl_uint i = 0; i < deviceListSize; ++i)
programBinaries[i] = new unsigned char[programBinarySizes[i]]; programBinaries[i] = new unsigned char[programBinarySizes[i]];
clGetProgramInfo((*program)(), err = clGetProgramInfo((*program)(), CL_PROGRAM_BINARIES,
CL_PROGRAM_BINARIES, sizeof(unsigned char *) * deviceListSize,
sizeof(unsigned char *) * deviceListSize, programBinaries, nullptr);
programBinaries, MACE_CHECK(err == CL_SUCCESS) << "Error code: " << err;
NULL); std::string content(reinterpret_cast<char const *>(programBinaries[0]),
std::string content(reinterpret_cast<char const*>(programBinaries[0]),
programBinarySizes[0]); programBinarySizes[0]);
WriteFile(binary_filename, content, true); MACE_CHECK(WriteFile(binary_filename, content, true));
} }
} }
cl::Kernel OpenCLRuntime::BuildKernel(const std::string &program_name, cl::Kernel
const std::string &kernel_name, OpenCLRuntime::BuildKernel(const std::string &program_name,
const std::set<std::string> &build_options) { const std::string &kernel_name,
const std::set<std::string> &build_options) {
auto kernel_program_it = program_map_.find(program_name); auto kernel_program_it = program_map_.find(program_name);
if (kernel_program_it == program_map_.end()) { if (kernel_program_it == program_map_.end()) {
MACE_CHECK(false, program_name, " opencl kernel doesn't exist."); MACE_CHECK(false, program_name, " opencl kernel doesn't exist.");
...@@ -288,7 +283,7 @@ cl::Kernel OpenCLRuntime::BuildKernel(const std::string &program_name, ...@@ -288,7 +283,7 @@ cl::Kernel OpenCLRuntime::BuildKernel(const std::string &program_name,
std::string program_file_name = kernel_program_it->second; std::string program_file_name = kernel_program_it->second;
std::string build_options_str; std::string build_options_str;
for(auto &option : build_options) { for (auto &option : build_options) {
build_options_str += " " + option; build_options_str += " " + option;
} }
std::string built_program_key = program_name + build_options_str; std::string built_program_key = program_name + build_options_str;
...@@ -299,12 +294,10 @@ cl::Kernel OpenCLRuntime::BuildKernel(const std::string &program_name, ...@@ -299,12 +294,10 @@ cl::Kernel OpenCLRuntime::BuildKernel(const std::string &program_name,
if (built_program_it != built_program_map_.end()) { if (built_program_it != built_program_map_.end()) {
program = built_program_it->second; program = built_program_it->second;
} else { } else {
std::string binary_file_name = built_program_key; std::string binary_file_name_prefix =
GenerateCLBinaryFilename(binary_file_name); GenerateCLBinaryFilenamePrefix(built_program_key);
this->BuildProgram(program_file_name, this->BuildProgram(program_file_name, binary_file_name_prefix,
binary_file_name, build_options_str, &program);
build_options_str,
&program);
built_program_map_.emplace(built_program_key, program); built_program_map_.emplace(built_program_key, program);
} }
return cl::Kernel(program, kernel_name.c_str()); return cl::Kernel(program, kernel_name.c_str());
...@@ -316,10 +309,10 @@ uint32_t OpenCLRuntime::GetDeviceMaxWorkGroupSize() { ...@@ -316,10 +309,10 @@ uint32_t OpenCLRuntime::GetDeviceMaxWorkGroupSize() {
return static_cast<uint32_t>(size); return static_cast<uint32_t>(size);
} }
uint32_t OpenCLRuntime::GetKernelMaxWorkGroupSize(const cl::Kernel& kernel) { uint32_t OpenCLRuntime::GetKernelMaxWorkGroupSize(const cl::Kernel &kernel) {
unsigned long long size = 0; unsigned long long size = 0;
kernel.getWorkGroupInfo(device_, CL_KERNEL_WORK_GROUP_SIZE, &size); kernel.getWorkGroupInfo(device_, CL_KERNEL_WORK_GROUP_SIZE, &size);
return static_cast<uint32_t>(size); return static_cast<uint32_t>(size);
} }
} // namespace mace } // namespace mace
...@@ -48,7 +48,7 @@ class OpenCLRuntime { ...@@ -48,7 +48,7 @@ class OpenCLRuntime {
const std::string &binary_file_name, const std::string &binary_file_name,
const std::string &build_options, const std::string &build_options,
cl::Program *program); cl::Program *program);
void GenerateCLBinaryFilename(std::string &filename); std::string GenerateCLBinaryFilenamePrefix(const std::string &filename_msg);
private: private:
static bool enable_profiling_; static bool enable_profiling_;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册