提交 8d86da87 编写于 作者: Y yejianwu

update codegen template, add distribute lib

上级 5553184f
......@@ -5,6 +5,8 @@ package(
default_visibility = ["//visibility:public"],
)
load("//mace:mace.bzl", "if_embed_binary_program", "if_use_source_program")
cc_library(
name = "generated_models_lib",
srcs = glob(["models/*/*.cc"]),
......@@ -13,12 +15,24 @@ cc_library(
deps = [
"//mace/core",
"//mace/ops",
"//mace/codegen:distribute_lib",
"//mace/codegen:version_lib",
"//mace/codegen:generated_opencl_lib",
"//mace/codegen:generated_tuning_lib",
],
)
cc_library(
name = "distribute_lib",
srcs = if_embed_binary_program(["distribute/use_binary.cc"]) +
if_use_source_program(["distribute/use_source.cc"]),
copts = ["-std=c++11", "-D_GLIBCXX_USE_C99_MATH_TR1", "-Werror=return-type"],
linkstatic = 1,
deps = [
"//mace/core",
],
)
cc_library(
name = "generated_opencl_lib",
srcs = glob(["opencl/*.cc"]),
......
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
#include "mace/core/runtime/opencl/cl2_header.h"
namespace mace {
bool GetSourceOrBinaryProgram(const std::string &program_name,
const std::string &binary_file_name_prefix,
cl::Context &context,
cl::Device &device,
cl::Program *program,
bool *is_binary) {
extern const std::map<std::string, std::vector<unsigned char>> kCompiledProgramMap;
*is_binary = true;
auto it_binary = kCompiledProgramMap.find(binary_file_name_prefix);
if (it_binary == kCompiledProgramMap.end()) {
return false;
}
*program = cl::Program(context, {device}, {it_binary->second});
return true;
}
bool GetTuningParams(const char *path,
std::unordered_map<std::string, std::vector<unsigned int>> *param_table) {
extern const std::map<std::string, std::vector<unsigned int>> kTuningParamsData;
for (auto it = kTuningParamsData.begin(); it != kTuningParamsData.end(); ++it) {
param_table->emplace(it->first, std::vector<unsigned int>(it->second.begin(), it->second.end()));
}
return true;
}
} // namespace mace
//
// Copyright (c) 2017 XiaoMi All rights reserved.
//
// This is a generated file, DO NOT EDIT
{% if mode == "read_tuning_config" %}
#include <fstream>
#include <map>
#include <string>
#include <vector>
#include <unordered_map>
#include <vector>
#include "mace/core/runtime/opencl/cl2_header.h"
namespace mace {
namespace {
inline void DecryptOpenCLSource(const std::vector<unsigned char> &src,
std::vector<unsigned char> *dst) {
dst->reserve(src.size());
// Keep consistent with encrypt in python tool
const std::string decrypt_lookup_table = "Xiaomi-AI-Platform-Mace";
size_t lookup_table_size = decrypt_lookup_table.size();
for (int i = 0; i < src.size(); i++) {
dst->push_back(src[i] ^ decrypt_lookup_table[i % lookup_table_size]);
}
}
} // namespace
bool GetSourceOrBinaryProgram(const std::string &program_name,
const std::string &binary_file_name_prefix,
cl::Context &context,
cl::Device &device,
cl::Program *program,
bool *is_binary) {
extern const std::map<std::string, std::vector<unsigned char>> kEncryptedProgramMap;
*is_binary = false;
auto it_source = kEncryptedProgramMap.find(program_name);
if (it_source == kEncryptedProgramMap.end()) {
return false;
}
cl::Program::Sources sources;
std::vector<unsigned char> decrypt_source;
DecryptOpenCLSource(it_source->second, &decrypt_source);
sources.push_back(std::string(decrypt_source.begin(), decrypt_source.end()));
*program = cl::Program(context, sources);
return true;
}
bool GetTuningParams(const char *path,
std::unordered_map<std::string, std::vector<{{data_type}}>> *param_table) {
std::unordered_map<std::string, std::vector<unsigned int>> *param_table) {
if (path != nullptr) {
std::ifstream ifs(path, std::ios::binary | std::ios::in);
if (ifs.is_open()) {
......@@ -27,10 +60,10 @@ bool GetTuningParams(const char *path,
ifs.read(&key[0], key_size);
ifs.read(reinterpret_cast<char *>(&params_size), sizeof(params_size));
params_count = params_size / sizeof({{data_type}});
std::vector<{{data_type}}> params(params_count);
params_count = params_size / sizeof(unsigned int);
std::vector<unsigned int> params(params_count);
for (int i = 0; i < params_count; ++i) {
ifs.read(reinterpret_cast<char *>(&params[i]), sizeof({{data_type}}));
ifs.read(reinterpret_cast<char *>(&params[i]), sizeof(unsigned int));
}
param_table->emplace(key, params);
}
......@@ -41,71 +74,5 @@ bool GetTuningParams(const char *path,
}
return true;
}
} // namespace
{% else %}
#include <map>
#include <string>
#include <vector>
{% if mode == "tuning_binary" %}
#include <unordered_map>
{% endif %}
namespace mace {
extern const std::map<std::string, std::vector<{{data_type}}>> {{variable_name}}=
{
{% for key, value in maps.iteritems() %}
{
"{{key}}",
{
{%- for ele in value -%}
{{ele}},
{%- endfor -%}
}
}, // {{key}}
{% endfor %}
};
{% if mode == "cl_encrypt" %}
bool GetOpenCLProgram(const std::string &program_name,
const std::string &binary_file_name_prefix,
std::vector<unsigned char> *program_vec,
bool *is_binary) {
*is_binary = false;
auto it_source = {{variable_name}}.find(program_name);
if (it_source == {{variable_name}}.end()) {
return false;
}
*program_vec = it_source->second;
return true;
}
{% elif mode == "cl_binary" %}
bool GetOpenCLProgram(const std::string &program_name,
const std::string &binary_file_name_prefix,
std::vector<unsigned char> *program_vec,
bool *is_binary) {
*is_binary = true;
auto it_source = {{variable_name}}.find(binary_file_name_prefix);
if (it_source == {{variable_name}}.end()) {
return false;
}
*program_vec = it_source->second;
return true;
}
{% elif mode == "tuning_binary" %}
bool GetTuningParams(const char *path,
std::unordered_map<std::string, std::vector<{{data_type}}>> *param_table) {
for (auto it = kTuningParamsData.begin(); it != kTuningParamsData.end(); ++it) {
param_table->emplace(it->first, std::vector<{{data_type}}>(it->second.begin(), it->second.end()));
}
return true;
}
{% endif %}
} // namespace
{% endif %}
} // namespace mace
......@@ -16,47 +16,6 @@
namespace mace {
namespace {
bool ReadFile(const std::string &filename,
bool binary,
std::vector<unsigned char> *content_ptr) {
MACE_CHECK_NOTNULL(content_ptr);
std::ios_base::openmode mode = std::ios::in;
if (binary) {
mode |= std::ios::binary;
}
std::ifstream ifs(filename, mode);
// Stop eating new lines and whitespace
ifs.unsetf(std::ios::skipws);
if (!ifs.is_open()) {
LOG(ERROR) << "Failed to open file " << filename;
return false;
}
ifs.seekg(0, std::ios::end);
const size_t filesize = ifs.tellg();
if (filesize > 10 * 1024 * 1024) {
LOG(ERROR) << "Filesize overflow 10MB";
return false;
}
content_ptr->reserve(filesize);
ifs.seekg(0, std::ios::beg);
content_ptr->insert(content_ptr->begin(), std::istreambuf_iterator<char>(ifs),
std::istreambuf_iterator<char>());
if (ifs.fail()) {
LOG(ERROR) << "Failed to read from file " << filename;
return false;
}
ifs.close();
return true;
}
bool WriteFile(const std::string &filename,
bool binary,
const std::vector<unsigned char> &content) {
......@@ -174,24 +133,13 @@ std::string OpenCLRuntime::GenerateCLBinaryFilenamePrefix(
return filename_prefix;
}
extern bool GetOpenCLProgram(
const std::string &program_name,
extern bool GetSourceOrBinaryProgram(const std::string &program_name,
const std::string &binary_file_name_prefix,
std::vector<unsigned char> *program_vec,
cl::Context &context,
cl::Device &device,
cl::Program *program,
bool *is_opencl_binary);
const std::vector<unsigned char>
OpenCLRuntime::DecryptOpenCLSource(const std::vector<unsigned char> &src) {
std::vector<unsigned char> res;
res.reserve(src.size());
std::string decrypt_lookup_table = "Xiaomi-AI-Platform-Mace";
size_t lookup_table_size = decrypt_lookup_table.size();
for (int i = 0; i < src.size(); i++) {
res.push_back(src[i] ^ decrypt_lookup_table[i % lookup_table_size]);
}
return res;
}
void OpenCLRuntime::BuildProgram(const std::string &program_name,
const std::string &binary_file_name_prefix,
const std::string &build_options,
......@@ -200,27 +148,18 @@ void OpenCLRuntime::BuildProgram(const std::string &program_name,
bool is_opencl_binary = false;
std::vector<unsigned char> program_vec;
const bool is_success = GetOpenCLProgram(program_name,
const bool found = GetSourceOrBinaryProgram(program_name,
binary_file_name_prefix,
&program_vec,
context(),
device(),
program,
&is_opencl_binary);
MACE_CHECK(is_success, "Failed in GetOpenCLProgram!");
if (is_opencl_binary) {
*program = cl::Program(this->context(), {device()}, {program_vec});
VLOG(1) << "Use opencl binaries";
} else {
cl::Program::Sources sources;
const std::vector<unsigned char> decrypt_source =
DecryptOpenCLSource(program_vec);
sources.push_back(std::string(decrypt_source.begin(), decrypt_source.end()));
*program = cl::Program(this->context(), sources);
VLOG(1) << "Use opencl sources";
}
MACE_CHECK(found, "Program not found source: ", program_name, ", or binary: ",
binary_file_name_prefix);
// Build program
std::string build_options_str =
build_options + " -Werror -cl-mad-enable -cl-fast-relaxed-math -I" +
kernel_path_;
build_options + " -Werror -cl-mad-enable -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());
if (ret != CL_SUCCESS) {
......
......@@ -55,7 +55,6 @@ class OpenCLRuntime {
const std::string &build_options,
cl::Program *program);
std::string GenerateCLBinaryFilenamePrefix(const std::string &filename_msg);
const std::vector<unsigned char> DecryptOpenCLSource(const std::vector<unsigned char> &src);
private:
// All OpenCL object must be a pointer and manually deleted before unloading
......
......@@ -30,6 +30,18 @@ def if_profiling_enabled(a):
"//conditions:default": [],
})
def if_embed_binary_program(a):
return select({
"//mace:embed_binary_program": a,
"//conditions:default": [],
})
def if_use_source_program(a):
return select({
"//mace:embed_binary_program": [],
"//conditions:default": a,
})
def if_enable_neon(a):
return select({
"//mace:enable_neon": a,
......
......@@ -38,11 +38,10 @@ def generate_cpp_source():
idx += params_size
env = jinja2.Environment(loader=jinja2.FileSystemLoader(sys.path[0]))
return env.get_template('embed_code.cc.tmpl').render(
return env.get_template('str2vec_maps.cc.tmpl').render(
maps = data_map,
data_type = 'unsigned int',
variable_name = FLAGS.variable_name,
mode="tuning_binary"
variable_name = FLAGS.variable_name
)
def main(unused_args):
......
......@@ -45,11 +45,10 @@ def main(unused_args):
encrypted_code_maps[file_name[:-3]] = encrypted_code_arr
env = jinja2.Environment(loader=jinja2.FileSystemLoader(sys.path[0]))
cpp_cl_encrypted_kernel = env.get_template('embed_code.cc.tmpl').render(
cpp_cl_encrypted_kernel = env.get_template('str2vec_maps.cc.tmpl').render(
maps=encrypted_code_maps,
data_type='unsigned char',
variable_name='kEncryptedProgramMap',
mode='cl_encrypt')
variable_name='kEncryptedProgramMap')
if os.path.isfile(FLAGS.output_path):
os.remove(FLAGS.output_path)
......
......@@ -27,11 +27,10 @@ def generate_cpp_source():
maps[file_name[:-4]].append(hex(ele))
env = jinja2.Environment(loader=jinja2.FileSystemLoader(sys.path[0]))
return env.get_template('embed_code.cc.tmpl').render(
return env.get_template('str2vec_maps.cc.tmpl').render(
maps = maps,
data_type = 'unsigned char',
variable_name = 'kCompiledProgramMap',
mode="cl_binary"
variable_name = 'kCompiledProgramMap'
)
......
//
// Copyright (c) 2017 XiaoMi All rights reserved.
//
// This is a generated file, DO NOT EDIT
#include <map>
#include <string>
#include <vector>
namespace mace {
extern const std::map<std::string, std::vector<{{data_type}}>> {{variable_name}}=
{
{% for key, value in maps.iteritems() %}
{
"{{key}}",
{
{%- for ele in value -%}
{{ele}},
{%- endfor -%}
}
}, // {{key}}
{% endfor %}
};
} // namespace
......@@ -104,7 +104,7 @@ class Tuner {
inline void ReadRunParamters() {
bool success = GetTuningParams(path_, &param_table_);
if (!success) {
LOG(WARNING) << "Read run parameter failed.";
LOG(WARNING) << "Get run parameter failed.";
}
}
......
......@@ -35,6 +35,9 @@ VERSION_SOURCE_PATH=${CODEGEN_DIR}/version
build_and_run()
{
EMBED_OPENCL_BINARY=$1
if [ "$EMBED_OPENCL_BINARY" = true ]; then
EMBED_OPENCL_BINARY_BUILD_FLAGS="--define embed_binary_program=true"
fi
bazel build -c opt --strip always mace/examples:mace_run \
--crosstool_top=//external:android/crosstool \
......@@ -44,6 +47,9 @@ build_and_run()
--copt=-DMACE_MODEL_FUNCTION=Create${MODEL_TAG}
adb shell "mkdir -p ${PHONE_DATA_DIR}"
if [ "$EMBED_OPENCL_BINARY" = false ]; then
adb shell "mkdir -p ${KERNEL_DIR}"
fi
adb push ${MODEL_DIR}/${INPUT_FILE_NAME} ${PHONE_DATA_DIR}
adb push bazel-bin/mace/examples/mace_run ${PHONE_DATA_DIR}
......@@ -99,13 +105,9 @@ bash mace/tools/git/gen_version_source.sh ${VERSION_SOURCE_PATH}/version.cc
echo "Step 4: Generate encrypted opencl source and read tuning method"
rm -rf ${CL_CODEGEN_DIR}
rm -rf ${TUNING_CODEGEN_DIR}
mkdir -p ${CL_CODEGEN_DIR}
mkdir -p ${TUNING_CODEGEN_DIR}
python mace/python/tools/encrypt_opencl_codegen.py \
--cl_kernel_dir=./mace/kernels/opencl/cl/ --output_path=${CL_CODEGEN_DIR}/opencl_encrypt_program.cc
python mace/python/tools/read_tuning_codegen.py \
--output_path=${TUNING_CODEGEN_DIR}/read_tuning_params.cc
echo "Step 5: Run model on the phone with files"
build_and_run false
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册