提交 2b87801b 编写于 作者: L liuqi

Refactor opencl built program storage logic.

上级 2446ddfd
......@@ -2,51 +2,48 @@
// Copyright (c) 2017 XiaoMi All rights reserved.
//
#include "mace/core/file_storage_engine.h"
#include "mace/core/file_storage.h"
#include <fstream>
#include <memory>
#include <utility>
#include "mace/utils/logging.h"
namespace mace {
std::string FileStorageEngine::kStoragePath // NOLINT(runtime/string)
= "/data/local/tmp";
class FileStorageFactory::Impl {
public:
explicit Impl(const std::string &path);
FileStorageEngine::FileStorageEngine(const std::string &file_name):
file_name_(file_name) {}
std::unique_ptr<KVStorage> CreateStorage(const std::string &name);
void FileStorageEngine::Write(
const std::map<std::string, std::vector<unsigned char>> &data) {
const std::string file_path = kStoragePath + "/" + file_name_;
private:
std::string path_;
};
std::ofstream ofs(file_path,
std::ios::binary | std::ios::out);
if (ofs.is_open()) {
int64_t data_size = data.size();
ofs.write(reinterpret_cast<const char *>(&data_size),
sizeof(data_size));
for (auto &kv : data) {
int32_t key_size = static_cast<int32_t>(kv.first.size());
ofs.write(reinterpret_cast<const char *>(&key_size), sizeof(key_size));
ofs.write(kv.first.c_str(), key_size);
FileStorageFactory::Impl::Impl(const std::string &path): path_(path) {}
std::unique_ptr<KVStorage> FileStorageFactory::Impl::CreateStorage(
const std::string &name) {
return std::move(std::unique_ptr<KVStorage>(
new FileStorage(path_ + "/" + name)));
}
int32_t value_size = static_cast<int32_t>(kv.second.size());
ofs.write(reinterpret_cast<const char *>(&value_size),
sizeof(value_size));
ofs.write(reinterpret_cast<const char*>(kv.second.data()),
value_size);
}
ofs.close();
} else {
LOG(WARNING) << "Write failed, please check directory exists";
}
FileStorageFactory::FileStorageFactory(const std::string &path):
impl_(new FileStorageFactory::Impl(path)) {}
FileStorageFactory::~FileStorageFactory() = default;
std::unique_ptr<KVStorage> FileStorageFactory::CreateStorage(
const std::string &name) {
return impl_->CreateStorage(name);
}
void FileStorageEngine::Read(
std::map<std::string, std::vector<unsigned char>> *data) {
const std::string file_path = kStoragePath + "/" + file_name_;
std::ifstream ifs(file_path, std::ios::binary | std::ios::in);
FileStorage::FileStorage(const std::string &file_path):
file_path_(file_path) {}
void FileStorage::Load() {
std::ifstream ifs(file_path_, std::ios::binary | std::ios::in);
if (ifs.is_open()) {
int64_t data_size = 0;
ifs.read(reinterpret_cast<char *>(&data_size), sizeof(data_size));
......@@ -60,10 +57,10 @@ void FileStorageEngine::Read(
ifs.read(reinterpret_cast<char *>(&value_size),
sizeof(value_size));
std::vector<unsigned char> program_binary(value_size);
ifs.read(reinterpret_cast<char *>(program_binary.data()),
std::vector<unsigned char> value(value_size);
ifs.read(reinterpret_cast<char *>(value.data()),
value_size);
data->emplace(key, program_binary);
data_.emplace(key, value);
}
ifs.close();
} else {
......@@ -71,4 +68,41 @@ void FileStorageEngine::Read(
}
}
bool FileStorage::Insert(const std::string &key,
const std::vector<unsigned char> &value) {
data_.emplace(key, value);
return true;
}
std::vector<unsigned char> *FileStorage::Find(const std::string &key) {
auto iter = data_.find(key);
if (iter == data_.end()) return nullptr;
return &(iter->second);
}
void FileStorage::Flush() {
std::ofstream ofs(file_path_,
std::ios::binary | std::ios::out);
if (ofs.is_open()) {
int64_t data_size = data_.size();
ofs.write(reinterpret_cast<const char *>(&data_size),
sizeof(data_size));
for (auto &kv : data_) {
int32_t key_size = static_cast<int32_t>(kv.first.size());
ofs.write(reinterpret_cast<const char *>(&key_size), sizeof(key_size));
ofs.write(kv.first.c_str(), key_size);
int32_t value_size = static_cast<int32_t>(kv.second.size());
ofs.write(reinterpret_cast<const char *>(&value_size),
sizeof(value_size));
ofs.write(reinterpret_cast<const char*>(kv.second.data()),
value_size);
}
ofs.close();
} else {
LOG(WARNING) << "Write failed, please check directory exists";
}
}
}; // namespace mace
......@@ -2,8 +2,8 @@
// Copyright (c) 2017 XiaoMi All rights reserved.
//
#ifndef MACE_CORE_FILE_STORAGE_ENGINE_H_
#define MACE_CORE_FILE_STORAGE_ENGINE_H_
#ifndef MACE_CORE_FILE_STORAGE_H_
#define MACE_CORE_FILE_STORAGE_H_
#include <map>
#include <string>
......@@ -13,21 +13,22 @@
namespace mace {
class FileStorageEngine : public KVStorageEngine {
class FileStorage : public KVStorage {
public:
explicit FileStorageEngine(const std::string &file_name);
public:
void Write(
const std::map<std::string, std::vector<unsigned char>> &data) override;
void Read(
std::map<std::string, std::vector<unsigned char>> *data) override;
private:
std::string file_name_;
explicit FileStorage(const std::string &file_path);
public:
static std::string kStoragePath;
void Load() override;
bool Insert(const std::string &key,
const std::vector<unsigned char> &value) override;
std::vector<unsigned char> *Find(const std::string &key) override;
void Flush() override;
private:
std::string file_path_;
std::map<std::string, std::vector<unsigned char>> data_;
};
} // namespace mace
#endif // MACE_CORE_FILE_STORAGE_ENGINE_H_
#endif // MACE_CORE_FILE_STORAGE_H_
......@@ -4,7 +4,7 @@
#include <memory>
#include "mace/core/file_storage_engine.h"
#include "mace/core/file_storage.h"
#include "mace/core/net.h"
#include "mace/core/runtime/hexagon/hexagon_control_wrapper.h"
#include "mace/core/runtime/opencl/opencl_runtime.h"
......@@ -69,8 +69,7 @@ class MaceEngine::Impl {
explicit Impl(const NetDef *net_def,
DeviceType device_type,
const std::vector<std::string> &input_nodes,
const std::vector<std::string> &output_nodes,
const std::string &internal_storage_path);
const std::vector<std::string> &output_nodes);
~Impl();
MaceStatus Run(const std::map<std::string, MaceTensor> &inputs,
......@@ -90,8 +89,7 @@ class MaceEngine::Impl {
MaceEngine::Impl::Impl(const NetDef *net_def,
DeviceType device_type,
const std::vector<std::string> &input_nodes,
const std::vector<std::string> &output_nodes,
const std::string &internal_storage_path)
const std::vector<std::string> &output_nodes)
: op_registry_(new OperatorRegistry()),
device_type_(device_type),
ws_(new Workspace()),
......@@ -99,7 +97,6 @@ MaceEngine::Impl::Impl(const NetDef *net_def,
hexagon_controller_(nullptr) {
LOG(INFO) << "MACE version: " << MaceVersion();
// Set storage path for internal usage
FileStorageEngine::kStoragePath = internal_storage_path;
for (auto input_name : input_nodes) {
ws_->CreateTensor(MakeString("mace_input_node_", input_name, ":0"),
GetDeviceAllocator(device_type_), DT_FLOAT);
......@@ -206,11 +203,9 @@ MaceStatus MaceEngine::Impl::Run(
MaceEngine::MaceEngine(const NetDef *net_def,
DeviceType device_type,
const std::vector<std::string> &input_nodes,
const std::vector<std::string> &output_nodes,
const std::string &internal_storage_path) {
const std::vector<std::string> &output_nodes) {
impl_ = std::unique_ptr<MaceEngine::Impl>(
new MaceEngine::Impl(net_def, device_type, input_nodes,
output_nodes, internal_storage_path));
new MaceEngine::Impl(net_def, device_type, input_nodes, output_nodes));
}
MaceEngine::~MaceEngine() = default;
......
......@@ -8,6 +8,8 @@
namespace mace {
std::shared_ptr<KVStorageFactory> kStorageFactory = nullptr;
void ConfigOpenCLRuntime(GPUPerfHint gpu_perf_hint,
GPUPriorityHint gpu_priority_hint) {
VLOG(1) << "Set GPU configurations, gpu_perf_hint: " << gpu_perf_hint
......@@ -15,9 +17,9 @@ void ConfigOpenCLRuntime(GPUPerfHint gpu_perf_hint,
OpenCLRuntime::Configure(gpu_perf_hint, gpu_priority_hint);
}
void ConfigKVStorageEngine(std::shared_ptr<KVStorageEngine> storage_engine) {
void ConfigKVStorageFactory(std::shared_ptr<KVStorageFactory> storage_factory) {
VLOG(1) << "Set internal KV Storage Engine";
OpenCLRuntime::Configure(storage_engine);
kStorageFactory = storage_factory;
}
void ConfigOmpThreads(int omp_num_threads) {
......
......@@ -12,7 +12,7 @@
#include <vector>
#include <utility>
#include "mace/core/file_storage_engine.h"
#include "mace/core/file_storage.h"
#include "mace/core/runtime/opencl/opencl_extension.h"
#include "mace/public/mace.h"
#include "mace/utils/tuner.h"
......@@ -182,7 +182,6 @@ void OpenCLProfilingTimer::ClearTiming() {
GPUPerfHint OpenCLRuntime::kGPUPerfHint = GPUPerfHint::PERF_DEFAULT;
GPUPriorityHint OpenCLRuntime::kGPUPriorityHint =
GPUPriorityHint::PRIORITY_DEFAULT;
std::shared_ptr<KVStorageEngine> OpenCLRuntime::kStorageEngine(nullptr);
OpenCLRuntime *OpenCLRuntime::Global() {
static OpenCLRuntime runtime(kGPUPerfHint, kGPUPriorityHint);
......@@ -194,9 +193,6 @@ void OpenCLRuntime::Configure(GPUPerfHint gpu_perf_hint,
OpenCLRuntime::kGPUPerfHint = gpu_perf_hint;
OpenCLRuntime::kGPUPriorityHint = gpu_priority_hint;
}
void OpenCLRuntime::Configure(std::shared_ptr<KVStorageEngine> storage_engine) {
OpenCLRuntime::kStorageEngine = std::move(storage_engine);
}
void GetAdrenoContextProperties(std::vector<cl_context_properties> *properties,
GPUPerfHint gpu_perf_hint,
......@@ -239,7 +235,8 @@ void GetAdrenoContextProperties(std::vector<cl_context_properties> *properties,
}
OpenCLRuntime::OpenCLRuntime(GPUPerfHint gpu_perf_hint,
GPUPriorityHint gpu_priority_hint) {
GPUPriorityHint gpu_priority_hint):
storage_(nullptr) {
LoadOpenCLLibrary();
std::vector<cl::Platform> all_platforms;
......@@ -312,17 +309,16 @@ OpenCLRuntime::OpenCLRuntime(GPUPerfHint gpu_perf_hint,
&err);
MACE_CHECK_CL_SUCCESS(err);
this->program_map_changed = false;
this->program_map_changed_ = false;
if (kStorageEngine == nullptr) {
extern std::shared_ptr<KVStorageFactory> kStorageFactory;
if (kStorageFactory != nullptr) {
const std::string cl_compiled_file_name = "mace_cl_compiled_program.bin";
kStorageEngine = std::move(
std::unique_ptr<FileStorageEngine>(
new FileStorageEngine(cl_compiled_file_name)));
}
storage_ = kStorageFactory->CreateStorage(cl_compiled_file_name);
if (platform_info_ != kCompiledProgramPlatform) {
kStorageEngine->Read(&program_content_map_);
if (platform_info_ != kCompiledProgramPlatform) {
storage_->Load();
}
}
}
......@@ -377,12 +373,13 @@ bool OpenCLRuntime::BuildProgramFromCache(
const std::string &build_options_str,
cl::Program *program) {
// Find from binary
auto it_content = this->program_content_map_.find(built_program_key);
if (it_content == this->program_content_map_.end()) {
if (this->storage_ == nullptr) return false;
auto content = this->storage_->Find(built_program_key);
if (content == nullptr) {
return false;
}
*program = cl::Program(context(), {device()}, {it_content->second});
*program = cl::Program(context(), {device()}, {*content});
cl_int ret = program->build({device()}, build_options_str.c_str());
if (ret != CL_SUCCESS) {
if (program->getBuildInfo<CL_PROGRAM_BUILD_STATUS>(device()) ==
......@@ -451,9 +448,11 @@ void OpenCLRuntime::BuildProgramFromSource(
reinterpret_cast<unsigned char const *>(program_binaries[0].get()) +
program_binary_sizes[0]);
this->program_content_map_.emplace(built_program_key,
content);
this->program_map_changed = true;
if (this->storage_ != nullptr) {
this->storage_->Insert(built_program_key, content);
this->program_map_changed_ = true;
}
VLOG(3) << "Program from source: " << built_program_key;
}
}
......@@ -504,9 +503,9 @@ cl::Kernel OpenCLRuntime::BuildKernel(
}
void OpenCLRuntime::SaveBuiltCLProgram() {
if (program_map_changed) {
kStorageEngine->Write(program_content_map_);
program_map_changed = false;
if (program_map_changed_ && storage_ != nullptr) {
storage_->Flush();
program_map_changed_ = false;
}
}
......
......@@ -56,7 +56,7 @@ class OpenCLRuntime {
public:
static OpenCLRuntime *Global();
static void Configure(GPUPerfHint, GPUPriorityHint);
static void Configure(std::shared_ptr<KVStorageEngine> storage_engine);
static void Configure(std::shared_ptr<KVStorage> storage_engine);
cl::Context &context();
cl::Device &device();
......@@ -108,16 +108,15 @@ class OpenCLRuntime {
std::shared_ptr<cl::Device> device_;
std::shared_ptr<cl::CommandQueue> command_queue_;
std::map<std::string, cl::Program> built_program_map_;
std::map<std::string, std::vector<unsigned char>> program_content_map_;
std::mutex program_build_mutex_;
GPUType gpu_type_;
std::string opencl_version_;
std::string platform_info_;
bool program_map_changed;
bool program_map_changed_;
std::unique_ptr<KVStorage> storage_;
static GPUPerfHint kGPUPerfHint;
static GPUPriorityHint kGPUPriorityHint;
static std::shared_ptr<KVStorageEngine> kStorageEngine;
};
} // namespace mace
......
......@@ -157,9 +157,13 @@ bool RunModel(const std::vector<std::string> &input_names,
const std::string kernel_file_path =
"/data/local/tmp/mace_run/cl";
// Config internal kv storage factory.
std::shared_ptr<KVStorageFactory> storage_factory(
new FileStorageFactory(kernel_file_path));
ConfigKVStorageFactory(storage_factory);
// Init model
mace::MaceEngine engine(&net_def, device_type, input_names,
output_names, kernel_file_path);
output_names);
if (device_type == DeviceType::OPENCL || device_type == DeviceType::HEXAGON) {
mace::MACE_MODEL_TAG::UnloadModelData(model_data);
}
......
......@@ -54,8 +54,7 @@ class MaceEngine {
explicit MaceEngine(const NetDef *net_def,
DeviceType device_type,
const std::vector<std::string> &input_nodes,
const std::vector<std::string> &output_nodes,
const std::string &internal_storage_path);
const std::vector<std::string> &output_nodes);
~MaceEngine();
MaceStatus Run(const std::map<std::string, MaceTensor> &inputs,
......
......@@ -31,16 +31,36 @@ enum GPUPriorityHint {
enum CPUPowerOption { DEFAULT = 0, HIGH_PERFORMANCE = 1, BATTERY_SAVE = 2 };
class KVStorageEngine {
class KVStorage {
public:
virtual void Write(
const std::map<std::string, std::vector<unsigned char>> &data) = 0;
virtual void Read(
std::map<std::string, std::vector<unsigned char>> *data) = 0;
virtual void Load() = 0;
virtual bool Insert(const std::string &key,
const std::vector<unsigned char> &value) = 0;
virtual std::vector<unsigned char> *Find(const std::string &key) = 0;
virtual void Flush() = 0;
};
class KVStorageFactory {
public:
virtual std::unique_ptr<KVStorage> CreateStorage(const std::string &name) = 0;
};
class FileStorageFactory : public KVStorageFactory {
public:
explicit FileStorageFactory(const std::string &path);
~FileStorageFactory();
std::unique_ptr<KVStorage> CreateStorage(const std::string &name) override;
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
void ConfigKVStorageFactory(std::shared_ptr<KVStorageFactory> storage_factory);
void ConfigOpenCLRuntime(GPUPerfHint, GPUPriorityHint);
void ConfigKVStorageEngine(std::shared_ptr<KVStorageEngine> storage_engine);
void ConfigOmpThreads(int omp_num_threads);
void ConfigCPUPowerOption(CPUPowerOption power_option);
......
......@@ -25,6 +25,7 @@ def generate_cpp_source():
with open(binary_path, "rb") as f:
binary_array = np.fromfile(f, dtype=np.uint8)
print "Generate binary", binary_path
idx = 0
size, = struct.unpack("Q", binary_array[idx:idx+8])
idx += 8
......
......@@ -14,15 +14,16 @@ FLAGS = None
def generate_cpp_source():
cl_built_kernel_file_name = 'mace_cl_compiled_program.bin'
cl_platform_info_file_name = 'mace_cl_platform_info.txt'
maps = {}
platform_info = ''
for binary_dir in FLAGS.cl_binary_dirs.split(","):
binary_path = os.path.join(binary_dir, cl_built_kernel_file_name)
binary_dirs = FLAGS.cl_binary_dirs.strip().split(",")
for binary_dir in binary_dirs:
binary_path = os.path.join(binary_dir, FLAGS.built_kernel_file_name)
print 'Before generate opencl code:', binary_path
if not os.path.exists(binary_path):
continue
print 'generate opencl code:', binary_path
with open(binary_path, "rb") as f:
binary_array = np.fromfile(f, dtype=np.uint8)
......@@ -43,7 +44,7 @@ def generate_cpp_source():
for ele in value:
maps[key].append(hex(ele))
cl_platform_info_path = os.path.join(binary_dir, cl_platform_info_file_name)
cl_platform_info_path = os.path.join(binary_dir, FLAGS.platform_info_file_name)
with open(cl_platform_info_path, 'r') as f:
curr_platform_info = f.read()
if platform_info != "":
......@@ -76,6 +77,16 @@ def parse_args():
type=str,
default="",
help="The cl binaries directories.")
parser.add_argument(
"--built_kernel_file_name",
type=str,
default="",
help="The cl binaries directories.")
parser.add_argument(
"--platform_info_file_name",
type=str,
default="",
help="The cl binaries directories.")
parser.add_argument(
"--output_path",
type=str,
......
......@@ -228,6 +228,9 @@ bool RunModel(const std::vector<std::string> &input_names,
// Init model
LOG(INFO) << "Run init";
std::shared_ptr<KVStorageFactory> storage_factory(
new FileStorageFactory(kernel_file_path));
ConfigKVStorageFactory(storage_factory);
mace::MaceEngine engine(&net_def, device_type, input_names, output_names);
if (device_type == DeviceType::OPENCL || device_type == DeviceType::HEXAGON) {
mace::MACE_MODEL_TAG::UnloadModelData(model_data);
......
......@@ -9,6 +9,8 @@ MODEL_CODEGEN_DIR=${CODEGEN_DIR}/models/${MODEL_TAG}
CL_CODEGEN_DIR=${CODEGEN_DIR}/opencl
TUNING_CODEGEN_DIR=${CODEGEN_DIR}/tuning
VERSION_SOURCE_PATH=${CODEGEN_DIR}/version
CL_BUILT_KERNEL_FILE_NAME=mace_cl_compiled_program.bin
CL_PLATFORM_INFO_FILE_NAME=mace_cl_platform_info.txt
if [ -z ${EMBED_MODEL_DATA} ]; then
EMBED_MODEL_DATA=1
fi
......
......@@ -26,6 +26,8 @@ if [ x"$TYPE" == x"source" ];then
elif [ x"$#" == x"1" ];then
python mace/python/tools/opencl_codegen.py \
--built_kernel_file_name=${CL_BUILT_KERNEL_FILE_NAME} \
--platform_info_file_name=${CL_PLATFORM_INFO_FILE_NAME} \
--output_path=${CL_CODEGEN_DIR}/opencl_compiled_program.cc || exit 1
else
......@@ -39,14 +41,17 @@ else
if [ "$PULL_OR_NOT" = 1 ]; then
CL_BIN_DIR=${CL_BIN_DIRS}
rm -rf ${CL_BIN_DIR}
mkdir -p ${CL_BIN_DIR}
rm -rf ${CL_BIN_DIR}/${CL_BUILT_KERNEL_FILE_NAME}
rm -rf ${CL_BIN_DIR}/${CL_PLATFORM_INFO_FILE_NAME}
if [ x"$TARGET_ABI" != x"host" ]; then
adb -s $DEVICE_ID pull ${COMPILED_PROGRAM_DIR}/. ${CL_BIN_DIR} > /dev/null
fi
fi
python mace/python/tools/opencl_codegen.py \
--built_kernel_file_name=${CL_BUILT_KERNEL_FILE_NAME} \
--platform_info_file_name=${CL_PLATFORM_INFO_FILE_NAME} \
--cl_binary_dirs=${CL_BIN_DIRS} \
--output_path=${CL_CODEGEN_DIR}/opencl_compiled_program.cc || exit 1
fi
......
......@@ -24,8 +24,8 @@ else
fi
if [ "$PULL_OR_NOT" = 1 ]; then
rm -rf ${BIN_DIRS}
mkdir -p ${BIN_DIRS}
rm -rf ${BIN_DIRS}/mace_run.config
if [ x"$TARGET_ABI" != x"host" ]; then
adb -s $DEVICE_ID pull ${PHONE_DATA_DIR}/mace_run.config ${BIN_DIRS} > /dev/null
fi
......
......@@ -251,7 +251,6 @@ def merge_libs_and_tuning_results(target_soc, output_dir, model_output_dirs):
build_production_code()
model_output_dirs_str = ",".join(model_output_dirs)
print output_dir, model_output_dirs
command = "bash tools/merge_libs.sh {} {} {}".format(target_soc, output_dir,
model_output_dirs_str)
run_command(command)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册