diff --git a/mace/benchmark/benchmark_model.cc b/mace/benchmark/benchmark_model.cc index da88f25ae92581712f094513ea1f6ba811841b4f..e23c3a02beb8cd40202c8d5aeedaa193513e6790 100644 --- a/mace/benchmark/benchmark_model.cc +++ b/mace/benchmark/benchmark_model.cc @@ -280,11 +280,13 @@ int Main(int argc, char **argv) { } } - std::vector model_weights_data; + const unsigned char *model_weights_data = nullptr; + size_t model_weights_data_size = 0; if (FLAGS_model_data_file != "") { - if (!mace::ReadBinaryFile(&model_weights_data, FLAGS_model_data_file)) { - LOG(FATAL) << "Failed to read file: " << FLAGS_model_data_file; - } + MemoryMap(FLAGS_model_data_file, + &model_weights_data, + &model_weights_data_size); + MACE_CHECK(model_weights_data != nullptr && model_weights_data_size != 0); } #ifdef MODEL_GRAPH_FORMAT_CODE @@ -300,8 +302,8 @@ int Main(int argc, char **argv) { create_engine_status = CreateMaceEngineFromProto(model_graph_data.data(), model_graph_data.size(), - model_weights_data.data(), - model_weights_data.size(), + model_weights_data, + model_weights_data_size, input_names, output_names, config, @@ -378,6 +380,10 @@ int Main(int argc, char **argv) { statistician->PrintStat(); + if (model_weights_data != nullptr) { + MemoryUnMap(model_weights_data, model_weights_data_size); + } + return 0; } diff --git a/mace/core/runtime/cpu/cpu_runtime.cc b/mace/core/runtime/cpu/cpu_runtime.cc index fb0b7e5924bd5d377c33d5d70f797d608522e251..c4ed389265a9881fd6505476ffe45f5852f1bc15 100644 --- a/mace/core/runtime/cpu/cpu_runtime.cc +++ b/mace/core/runtime/cpu/cpu_runtime.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/mace/examples/cli/example.cc b/mace/examples/cli/example.cc index 3a984f96aaf79b2b88f059b0315621b39a1f7002..15ab07804de9365dbd2d0b06b7c263e0951d9947 100644 --- a/mace/examples/cli/example.cc +++ b/mace/examples/cli/example.cc @@ -13,9 +13,14 @@ // limitations under the License. #include +#include #include -#include +#include +#include +#include +#include #include +#include #include #include #include @@ -80,6 +85,55 @@ bool ReadBinaryFile(std::vector *data, return true; } + +bool MemoryMap(const std::string &file, + const unsigned char **data, + size_t *size) { + bool ret = true; + int fd = open(file.c_str(), O_RDONLY); + if (fd < 0) { + std::cerr << "Failed to open file " << file + << ", error code: " << strerror(errno) << std::endl; + ret = false; + } + struct stat st; + fstat(fd, &st); + *size = static_cast(st.st_size); + + *data = static_cast( + mmap(nullptr, *size, PROT_READ, MAP_PRIVATE, fd, 0)); + if (*data == static_cast(MAP_FAILED)) { + std::cerr << "Failed to map file " << file + << ", error code: " << strerror(errno) << std::endl; + ret = false; + } + + if (close(fd) < 0) { + std::cerr << "Failed to close file " << file + << ", error code: " << strerror(errno) << std::endl; + ret = false; + } + + return ret; +} + +bool MemoryUnMap(const unsigned char *data, + const size_t &size) { + bool ret = true; + if (data == nullptr || size == 0) { + std::cerr << "data is null or size is 0" << std::endl; + ret = false; + } + + if (munmap(const_cast(data), size) < 0) { + std::cerr << "Failed to unmap file, error code: " + << strerror(errno) << std::endl; + ret = false; + } + + return ret; +} + } // namespace void ParseShape(const std::string &str, std::vector *shape) { @@ -178,7 +232,7 @@ bool RunModel(const std::vector &input_names, MaceEngineConfig config(device_type); status = config.SetCPUThreadPolicy( FLAGS_omp_num_threads, - static_cast(FLAGS_cpu_affinity_policy)); + static_cast(FLAGS_cpu_affinity_policy)); if (status != MaceStatus::MACE_SUCCESS) { std::cerr << "Set openmp or cpu affinity failed." << std::endl; } @@ -216,8 +270,11 @@ bool RunModel(const std::vector &input_names, if (!ReadBinaryFile(&model_graph_data, FLAGS_model_file)) { std::cerr << "Failed to read file: " << FLAGS_model_file << std::endl; } - std::vector model_weights_data; - if (!ReadBinaryFile(&model_weights_data, FLAGS_model_data_file)) { + const unsigned char *model_weights_data = nullptr; + size_t model_weights_data_size = 0; + if (!MemoryMap(FLAGS_model_data_file, + &model_weights_data, + &model_weights_data_size)) { std::cerr << "Failed to read file: " << FLAGS_model_data_file << std::endl; } @@ -238,8 +295,8 @@ bool RunModel(const std::vector &input_names, create_engine_status = CreateMaceEngineFromProto(model_graph_data.data(), model_graph_data.size(), - model_weights_data.data(), - model_weights_data.size(), + model_weights_data, + model_weights_data_size, input_names, output_names, config, @@ -373,6 +430,10 @@ bool RunModel(const std::vector &input_names, } } + if (model_weights_data != nullptr) { + MemoryUnMap(model_weights_data, model_weights_data_size); + } + std::cout << "Finished" << std::endl; return true; diff --git a/mace/libmace/mace.cc b/mace/libmace/mace.cc index 12bdf2be5f511e5ba3d79d230f1270e8db9ed158..ce8a1cc77af08e027c91ed5c57e3b49a55ba7ada 100644 --- a/mace/libmace/mace.cc +++ b/mace/libmace/mace.cc @@ -12,12 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include -#include -#include -#include -#include - #include #include #include @@ -41,33 +35,6 @@ namespace mace { namespace { -const unsigned char *LoadModelData(const std::string &model_data_file, - const size_t &data_size) { - int fd = open(model_data_file.c_str(), O_RDONLY); - MACE_CHECK(fd >= 0, "Failed to open model data file ", - model_data_file, ", error code: ", strerror(errno)); - - const unsigned char *model_data = static_cast( - mmap(nullptr, data_size, PROT_READ, MAP_PRIVATE, fd, 0)); - MACE_CHECK(model_data != MAP_FAILED, "Failed to map model data file ", - model_data_file, ", error code: ", strerror(errno)); - - int ret = close(fd); - MACE_CHECK(ret == 0, "Failed to close model data file ", - model_data_file, ", error code: ", strerror(errno)); - - return model_data; -} - -void UnloadModelData(const unsigned char *model_data, - const size_t &data_size) { - MACE_CHECK(model_data != nullptr && data_size > 0, - "model_data is null or data_size is 0"); - int ret = munmap(const_cast(model_data), - data_size); - MACE_CHECK(ret == 0, "Failed to unmap model data file, error code: ", - strerror(errno)); -} #ifdef MACE_ENABLE_OPENCL MaceStatus CheckGPUAvalibility(const NetDef *net_def, Device *device) { @@ -557,20 +524,14 @@ MaceStatus MaceEngine::Impl::Init( const std::vector &output_nodes, const std::string &model_data_file) { LOG(INFO) << "Loading Model Data"; - for (auto &const_tensor : net_def->tensors()) { - model_data_size_ = std::max( - model_data_size_, - static_cast(const_tensor.offset() + - const_tensor.data_size() * - GetEnumTypeSize(const_tensor.data_type()))); - } - model_data_ = LoadModelData(model_data_file, model_data_size_); + + MemoryMap(model_data_file, &model_data_, &model_data_size_); MACE_RETURN_IF_ERROR(Init(net_def, input_nodes, output_nodes, model_data_)); if (device_type_ == DeviceType::GPU || device_type_ == DeviceType::HEXAGON || (device_type_ == DeviceType::CPU && ws_->diffused_buffer())) { - UnloadModelData(model_data_, model_data_size_); + MemoryUnMap(model_data_, model_data_size_); model_data_ = nullptr; } return MaceStatus::MACE_SUCCESS; @@ -579,7 +540,7 @@ MaceStatus MaceEngine::Impl::Init( MaceEngine::Impl::~Impl() { LOG(INFO) << "Destroying MaceEngine"; if (model_data_ != nullptr) { - UnloadModelData(model_data_, model_data_size_); + MemoryUnMap(model_data_, model_data_size_); } #ifdef MACE_ENABLE_HEXAGON if (device_type_ == HEXAGON) { diff --git a/mace/tools/validation/mace_run.cc b/mace/tools/validation/mace_run.cc index 3e1c88741ab27ef6c2f3ed5144765448dee3ea00..c4d30765dbff06839140cb136417c3739cc03445 100644 --- a/mace/tools/validation/mace_run.cc +++ b/mace/tools/validation/mace_run.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -208,6 +209,8 @@ bool RunModel(const std::string &model_name, const std::vector &output_names, const std::vector> &output_shapes) { DeviceType device_type = ParseDeviceType(FLAGS_device); + + int64_t t0 = NowMicros(); // config runtime MaceStatus status; MaceEngineConfig config(device_type); @@ -247,17 +250,18 @@ bool RunModel(const std::string &model_name, } } - std::vector model_weights_data; + const unsigned char *model_weights_data = nullptr; + size_t model_weights_data_size = 0; if (FLAGS_model_data_file != "") { - if (!mace::ReadBinaryFile(&model_weights_data, FLAGS_model_data_file)) { - LOG(FATAL) << "Failed to read file: " << FLAGS_model_data_file; - } + MemoryMap(FLAGS_model_data_file, + &model_weights_data, + &model_weights_data_size); + MACE_CHECK(model_weights_data != nullptr && model_weights_data_size != 0); } std::shared_ptr engine; MaceStatus create_engine_status; - double init_millis; while (true) { // Create Engine int64_t t0 = NowMicros(); @@ -275,8 +279,8 @@ bool RunModel(const std::string &model_name, create_engine_status = CreateMaceEngineFromProto(model_graph_data.data(), model_graph_data.size(), - model_weights_data.data(), - model_weights_data.size(), + model_weights_data, + model_weights_data_size, input_names, output_names, config, @@ -288,11 +292,15 @@ bool RunModel(const std::string &model_name, LOG(ERROR) << "Create engine runtime error, retry ... errcode: " << create_engine_status.information(); } else { - init_millis = (t1 - t0) / 1000.0; - LOG(INFO) << "Total init latency: " << init_millis << " ms"; + double create_engine_millis = (t1 - t0) / 1000.0; + LOG(INFO) << "Create Mace Engine latency: " << create_engine_millis + << " ms"; break; } } + int64_t t1 = NowMicros(); + double init_millis = (t1 - t0) / 1000.0; + LOG(INFO) << "Total init latency: " << init_millis << " ms"; const size_t input_count = input_names.size(); const size_t output_count = output_names.size(); @@ -351,8 +359,8 @@ bool RunModel(const std::string &model_name, create_engine_status = CreateMaceEngineFromProto(model_graph_data.data(), model_graph_data.size(), - model_weights_data.data(), - model_weights_data.size(), + model_weights_data, + model_weights_data_size, input_names, output_names, config, @@ -394,8 +402,8 @@ bool RunModel(const std::string &model_name, create_engine_status = CreateMaceEngineFromProto(model_graph_data.data(), model_graph_data.size(), - model_weights_data.data(), - model_weights_data.size(), + model_weights_data, + model_weights_data_size, input_names, output_names, config, @@ -441,6 +449,10 @@ bool RunModel(const std::string &model_name, << output_size << " done."; } + if (model_weights_data != nullptr) { + MemoryUnMap(model_weights_data, model_weights_data_size); + } + return true; } diff --git a/mace/utils/BUILD b/mace/utils/BUILD index 283efa490e0a54ed48df9a61a289e5b67bf503f8..4388e1a6628de7f738cb2a971d9a9c8f29022bd3 100644 --- a/mace/utils/BUILD +++ b/mace/utils/BUILD @@ -7,14 +7,22 @@ package( licenses(["notice"]) # Apache 2.0 -load("//mace:mace.bzl", "if_android") +load( + "//mace:mace.bzl", + "if_android", + "if_openmp_enabled", +) cc_library( name = "utils", - srcs = [ - "logging.cc", - "string_util.cc", - ], + srcs = glob( + [ + "*.cc", + ], + exclude = [ + "tuner_test.cc", + ], + ), hdrs = glob([ "*.h", ]), @@ -22,7 +30,9 @@ cc_library( "-Werror", "-Wextra", "-Wno-missing-field-initializers", - ], + ] + if_openmp_enabled([ + "-fopenmp", + ]), linkopts = if_android([ "-llog", ]), diff --git a/mace/utils/tuner_development.cc b/mace/utils/tuner_development.cc deleted file mode 100644 index c760a0dcc6c1ee31ca9af0c178d6ecf83959153b..0000000000000000000000000000000000000000 --- a/mace/utils/tuner_development.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2018 The MACE Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include - -namespace mace { - -bool GetTuningParams( - const char *path, - std::unordered_map> *param_table) { - if (path != nullptr) { - std::ifstream ifs(path, std::ios::binary | std::ios::in); - if (ifs.is_open()) { - int64_t num_params = 0; - ifs.read(reinterpret_cast(&num_params), sizeof(num_params)); - while (num_params--) { - int32_t key_size = 0; - ifs.read(reinterpret_cast(&key_size), sizeof(key_size)); - std::string key(key_size, ' '); - ifs.read(&key[0], key_size); - - int32_t params_size = 0; - ifs.read(reinterpret_cast(¶ms_size), sizeof(params_size)); - int32_t params_count = params_size / sizeof(unsigned int); - std::vector params(params_count); - for (int i = 0; i < params_count; ++i) { - ifs.read(reinterpret_cast(¶ms[i]), sizeof(unsigned int)); - } - param_table->emplace(key, params); - } - ifs.close(); - } else { - return false; - } - } - return true; -} - -} // namespace mace diff --git a/mace/utils/tuner_production.cc b/mace/utils/tuner_production.cc deleted file mode 100644 index 18315ce66427bfc8ab7f02e9295eeac9504f9913..0000000000000000000000000000000000000000 --- a/mace/utils/tuner_production.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2018 The MACE Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include - -namespace mace { - -bool GetTuningParams( - const char *path, - std::unordered_map> *param_table) { - (void)(path); - extern const std::map> - kTuningParamsData; - for (auto it = kTuningParamsData.begin(); it != kTuningParamsData.end(); - ++it) { - param_table->emplace(it->first, std::vector( - it->second.begin(), it->second.end())); - } - return true; -} - -} // namespace mace diff --git a/mace/utils/utils.cc b/mace/utils/utils.cc new file mode 100644 index 0000000000000000000000000000000000000000..a422988d1689353a720e19ca544859dd5f952a68 --- /dev/null +++ b/mace/utils/utils.cc @@ -0,0 +1,146 @@ +// Copyright 2018 The MACE Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "mace/utils/utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mace/utils/logging.h" + +namespace mace { + +std::string ObfuscateString(const std::string &src, + const std::string &lookup_table) { + std::string dest; + dest.resize(src.size()); + for (size_t i = 0; i < src.size(); i++) { + dest[i] = src[i] ^ lookup_table[i % lookup_table.size()]; + } + return dest; +} + +// ObfuscateString(ObfuscateString(str)) ==> str +std::string ObfuscateString(const std::string &src) { + // Keep consistent with obfuscation in python tools + return ObfuscateString(src, "Mobile-AI-Compute-Engine"); +} + +// Obfuscate synbol or path string +std::string ObfuscateSymbol(const std::string &src) { + std::string dest = src; + if (dest.empty()) { + return dest; + } + dest[0] = src[0]; // avoid invalid symbol which starts from 0-9 + const std::string encode_dict = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; + for (size_t i = 1; i < src.size(); i++) { + char ch = src[i]; + int idx; + if (ch >= '0' && ch <= '9') { + idx = ch - '0'; + } else if (ch >= 'a' && ch <= 'z') { + idx = 10 + ch - 'a'; + } else if (ch >= 'A' && ch <= 'Z') { + idx = 10 + 26 + ch - 'a'; + } else if (ch == '_') { + idx = 10 + 26 + 26; + } else { + dest[i] = ch; + continue; + } + // There is no collision if it's true for every char at every position + dest[i] = encode_dict[(idx + i + 31) % encode_dict.size()]; + } + return dest; +} + +std::vector Split(const std::string &str, char delims) { + std::vector result; + std::string tmp = str; + while (!tmp.empty()) { + size_t next_offset = tmp.find(delims); + result.push_back(tmp.substr(0, next_offset)); + if (next_offset == std::string::npos) { + break; + } else { + tmp = tmp.substr(next_offset + 1); + } + } + return result; +} + +bool ReadBinaryFile(std::vector *data, + const std::string &filename) { + std::ifstream ifs(filename, std::ios::in | std::ios::binary); + if (!ifs.is_open()) { + return false; + } + ifs.seekg(0, ifs.end); + size_t length = ifs.tellg(); + ifs.seekg(0, ifs.beg); + + data->resize(length); + ifs.read(reinterpret_cast(data->data()), length); + + if (ifs.fail()) { + return false; + } + ifs.close(); + + return true; +} + +void MemoryMap(const std::string &file, + const unsigned char **data, + size_t *size) { + int fd = open(file.c_str(), O_RDONLY); + MACE_CHECK(fd >= 0, + "Failed to open file ", file, ", error code: ", strerror(errno)); + struct stat st; + fstat(fd, &st); + *size = static_cast(st.st_size); + + *data = static_cast( + mmap(nullptr, *size, PROT_READ, MAP_PRIVATE, fd, 0)); + MACE_CHECK(*data != static_cast(MAP_FAILED), + "Failed to map file ", file, ", error code: ", strerror(errno)); + + int ret = close(fd); + MACE_CHECK(ret == 0, + "Failed to close file ", file, ", error code: ", strerror(errno)); +} + +void MemoryUnMap(const unsigned char *data, + const size_t &size) { + MACE_CHECK(data != nullptr && size > 0, "data is null or size is 0"); + + int ret = munmap(const_cast(data), size); + + MACE_CHECK(ret == 0, + "Failed to unmap file, error code: ", strerror(errno)); +} + +} // namespace mace diff --git a/mace/utils/utils.h b/mace/utils/utils.h index 5bfd8609a70c9df05a3d6c56761da25a6387d976..0b1a6992c0d6240e62516379b34eda2a313cf74f 100644 --- a/mace/utils/utils.h +++ b/mace/utils/utils.h @@ -15,12 +15,9 @@ #ifndef MACE_UTILS_UTILS_H_ #define MACE_UTILS_UTILS_H_ -#include +#include #include -#include #include -#include -#include #include namespace mace { @@ -70,51 +67,12 @@ Integer CeilQuotient(Integer a, Integer b) { return (a + b - 1) / b; } -inline std::string ObfuscateString(const std::string &src, - const std::string &lookup_table) { - std::string dest; - dest.resize(src.size()); - for (size_t i = 0; i < src.size(); i++) { - dest[i] = src[i] ^ lookup_table[i % lookup_table.size()]; - } - return dest; -} +std::string ObfuscateString(const std::string &src, + const std::string &lookup_table); -// ObfuscateString(ObfuscateString(str)) ==> str -inline std::string ObfuscateString(const std::string &src) { - // Keep consistent with obfuscation in python tools - return ObfuscateString(src, "Mobile-AI-Compute-Engine"); -} +std::string ObfuscateString(const std::string &src); -// Obfuscate synbol or path string -inline std::string ObfuscateSymbol(const std::string &src) { - std::string dest = src; - if (dest.empty()) { - return dest; - } - dest[0] = src[0]; // avoid invalid symbol which starts from 0-9 - const std::string encode_dict = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; - for (size_t i = 1; i < src.size(); i++) { - char ch = src[i]; - int idx; - if (ch >= '0' && ch <= '9') { - idx = ch - '0'; - } else if (ch >= 'a' && ch <= 'z') { - idx = 10 + ch - 'a'; - } else if (ch >= 'A' && ch <= 'Z') { - idx = 10 + 26 + ch - 'a'; - } else if (ch == '_') { - idx = 10 + 26 + 26; - } else { - dest[i] = ch; - continue; - } - // There is no collision if it's true for every char at every position - dest[i] = encode_dict[(idx + i + 31) % encode_dict.size()]; - } - return dest; -} +std::string ObfuscateSymbol(const std::string &src); #ifdef MACE_OBFUSCATE_LITERALS #define MACE_OBFUSCATE_STRING(str) ObfuscateString(str) @@ -124,41 +82,17 @@ inline std::string ObfuscateSymbol(const std::string &src) { #define MACE_OBFUSCATE_SYMBOL(str) (str) #endif -inline std::vector Split(const std::string &str, char delims) { - std::vector result; - std::string tmp = str; - while (!tmp.empty()) { - size_t next_offset = tmp.find(delims); - result.push_back(tmp.substr(0, next_offset)); - if (next_offset == std::string::npos) { - break; - } else { - tmp = tmp.substr(next_offset + 1); - } - } - return result; -} +std::vector Split(const std::string &str, char delims); -inline bool ReadBinaryFile(std::vector *data, - const std::string &filename) { - std::ifstream ifs(filename, std::ios::in | std::ios::binary); - if (!ifs.is_open()) { - return false; - } - ifs.seekg(0, ifs.end); - size_t length = ifs.tellg(); - ifs.seekg(0, ifs.beg); - - data->reserve(length); - data->insert(data->begin(), std::istreambuf_iterator(ifs), - std::istreambuf_iterator()); - if (ifs.fail()) { - return false; - } - ifs.close(); +bool ReadBinaryFile(std::vector *data, + const std::string &filename); - return true; -} +void MemoryMap(const std::string &file, + const unsigned char **data, + size_t *size); + +void MemoryUnMap(const unsigned char *data, + const size_t &size); template std::vector MapKeys(const std::map &data) {