diff --git a/CMakeLists.txt b/CMakeLists.txt index 27b01993b3d0c16562abbb076e66d9860270ed46..0d25d5022fc3736d0b5bfd753422e24c4ae2a3de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,11 @@ cmake_minimum_required(VERSION 3.0.0) # basic build option -option(USE_OPENMP "build with openmp support" ON) +if(IS_IOS) + option(USE_OPENMP "build with openmp support" OFF) +else() + option(USE_OPENMP "build with openmp support" ON) +endif() option(USE_EXCEPTION "build with exception" ON) option(WITH_LOGGING "print logging for debug" OFF) option(WITH_SYMBOL "build with all symbols" ON) # turn off if use jni or ios io diff --git a/src/common/types.h b/src/common/types.h index bfffe9157568bbcdfe633c23f437052760b0acc6..8c16eb62b7d43fc621b28b4600858a8b94b90aa4 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -141,6 +141,7 @@ enum MemoryOptimizationLevel { struct PaddleMobileConfigInternal { bool load_when_predict = false; MemoryOptimizationLevel memory_optimization_level = FullMemoryOptimization; + std::string model_obfuscate_key = ""; }; extern const char *G_OP_TYPE_CONV; diff --git a/src/common/util.cpp b/src/common/util.cpp index 728653ecf03897d4a4aefe01bfcfefe1a07a47a2..acdc42e87926c3c66d9a855e27966d41cf43d5b5 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -32,4 +32,15 @@ char *ReadFileToBuff(std::string filename) { return data; } +int GetFileLength(std::string filename) { + FILE *file = fopen(filename.c_str(), "rb"); + PADDLE_MOBILE_ENFORCE(file != nullptr, "can't open file: %s ", + filename.c_str()); + fseek(file, 0, SEEK_END); + int size = ftell(file); + PADDLE_MOBILE_ENFORCE(size > 0, "file should not be empty"); + fclose(file); + return size; +} + } // namespace paddle_mobile diff --git a/src/common/util.h b/src/common/util.h index e4646c43f769583aace9d14c68e0e57ffa76f27d..212362a52e75edcdf9eca8857d197e7627e65f02 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -21,4 +21,6 @@ namespace paddle_mobile { char *ReadFileToBuff(std::string filename); +int GetFileLength(std::string filename); + } // namespace paddle_mobile diff --git a/src/framework/executor.cpp b/src/framework/executor.cpp index 296f8215b323c81c9a7dca9a971a9a66cff9425b..c06abc841631a59711e7c8cf524626be2ed2be78 100644 --- a/src/framework/executor.cpp +++ b/src/framework/executor.cpp @@ -30,6 +30,7 @@ limitations under the License. */ #include "framework/tensor.h" #include "memory/t_malloc.h" #include "pass/memory_optimize.h" +#include "pass/model_obfuscate.h" #ifdef PADDLE_MOBILE_CL #include "framework/cl/cl_image.h" #endif @@ -241,9 +242,17 @@ void Executor::InitCombineMemory() { if (program_.combined_params_buf && program_.combined_params_len) { origin_data = reinterpret_cast( const_cast(program_.combined_params_buf)); + if (config_.model_obfuscate_key != "") { + auto obfuscator = pass::ModelObfuscatePass(config_.model_obfuscate_key); + obfuscator.convert_data(origin_data, program_.combined_params_len); + } } else { self_alloc = true; origin_data = ReadFileToBuff(program_.para_path); + if (config_.model_obfuscate_key != "") { + auto obfuscator = pass::ModelObfuscatePass(config_.model_obfuscate_key); + obfuscator.convert_data(origin_data, GetFileLength(program_.para_path)); + } } PADDLE_MOBILE_ENFORCE(origin_data != nullptr, "data == nullptr"); char *data = origin_data; @@ -930,10 +939,18 @@ void Executor::InitCombineMemory() { if (program_.combined_params_buf && program_.combined_params_len) { LOG(kLOG_INFO) << "use outter memory"; origin_data = reinterpret_cast(program_.combined_params_buf); + if (config_.model_obfuscate_key != "") { + auto obfuscator = pass::ModelObfuscatePass(config_.model_obfuscate_key); + obfuscator.convert_data(origin_data, program_.combined_params_len); + } } else { LOG(kLOG_INFO) << " begin init combine memory"; self_alloc = true; origin_data = ReadFileToBuff(program_.para_path); + if (config_.model_obfuscate_key != "") { + auto obfuscator = pass::ModelObfuscatePass(config_.model_obfuscate_key); + obfuscator.convert_data(origin_data, GetFileLength(program_.para_path)); + } } PADDLE_MOBILE_ENFORCE(origin_data != nullptr, "origin_data==nullptr!!!"); float *data = reinterpret_cast(origin_data); diff --git a/src/pass/memory_optimize.cpp b/src/pass/memory_optimize.cpp index 3de5021bc9ba75fc6271c42831f6bc07355070b3..dc14bac15b2b09af7b822b0456a65105ec40b224 100644 --- a/src/pass/memory_optimize.cpp +++ b/src/pass/memory_optimize.cpp @@ -13,8 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "pass/memory_optimize.h" -#include "framework/lod_tensor.h" #include +#include "framework/lod_tensor.h" namespace paddle_mobile { namespace pass { diff --git a/src/pass/memory_optimize.h b/src/pass/memory_optimize.h index 991419dc33cdd769e49a534175bb959ad7fd4ffd..f0171c5ba6951ace2efac2fc5840b8878df3d1de 100644 --- a/src/pass/memory_optimize.h +++ b/src/pass/memory_optimize.h @@ -19,6 +19,7 @@ limitations under the License. */ #include #include #include "framework/program/program.h" +#include "pass/pass_base.h" namespace paddle_mobile { namespace pass { @@ -29,12 +30,6 @@ typedef struct { bool visited; } VarNode; -class PassBase { - public: - PassBase() {} - virtual ~PassBase() {} -}; - // MemoryOptPass will analyze the program, and reuse memory between // variables as much as possible class MemoryOptPass : public PassBase { diff --git a/src/pass/model_obfuscate.cpp b/src/pass/model_obfuscate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..913b93af25b4cd4b0de0e17571eb62af33401884 --- /dev/null +++ b/src/pass/model_obfuscate.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2018 PaddlePaddle 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 "pass/model_obfuscate.h" + +namespace paddle_mobile { +namespace pass { + +ModelObfuscatePass::ModelObfuscatePass(std::string key) { + for (auto c : key) { + acc *= base; + acc += (int)c; + acc %= stride; + } + acc += stride; +} + +void ModelObfuscatePass::convert_data(char *data, int len) { + for (int i = 0; i < len; i += acc) { + data[i] = 255 - data[i]; + } +} + +} // namespace pass +} // namespace paddle_mobile diff --git a/src/pass/model_obfuscate.h b/src/pass/model_obfuscate.h new file mode 100644 index 0000000000000000000000000000000000000000..6c2912e05afeb757f1671ce4feea5915ad11b046 --- /dev/null +++ b/src/pass/model_obfuscate.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2018 PaddlePaddle 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. */ + +#pragma once + +#include +#include "pass/pass_base.h" + +namespace paddle_mobile { +namespace pass { + +class ModelObfuscatePass : public PassBase { + public: + ModelObfuscatePass(std::string key); + void convert_data(char *data, int len); + int version = 1; + + private: + int acc = 0; + int base = 17; + int stride = 100; +}; + +} // namespace pass +} // namespace paddle_mobile diff --git a/src/pass/pass_base.h b/src/pass/pass_base.h new file mode 100644 index 0000000000000000000000000000000000000000..925fdb7d506c2742d14c2543c9d855116adcb7a8 --- /dev/null +++ b/src/pass/pass_base.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2018 PaddlePaddle 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. */ + +#pragma once + +namespace paddle_mobile { +namespace pass { + +class PassBase { + public: + PassBase() {} + virtual ~PassBase() {} +}; + +} // namespace pass +} // namespace paddle_mobile diff --git a/test/net/test_net.cpp b/test/net/test_net.cpp index 59a0e63d6e8b00fb12a662bbbd20d428fbce41df..2d87e1f725db840928509f409ec873633dbb9fd6 100644 --- a/test/net/test_net.cpp +++ b/test/net/test_net.cpp @@ -14,6 +14,7 @@ limitations under the License. */ #include #include +#include #include "../test_helper.h" #include "../test_include.h" @@ -34,6 +35,15 @@ void test(int argc, char *argv[]) { config.memory_optimization_level = enable_memory_optimization ? MemoryOptimizationWithoutFeeds : NoMemoryOptimization; + + // save obfuscated model + // config.model_obfuscate_key = "asdf"; + // std::ofstream out_file("new-params", std::ofstream::binary); + // char *out_data = ReadFileToBuff("./checked_model/params"); + // int len = GetFileLength("./checked_model/params"); + // out_file.write(out_data, len); + // out_file.close(); + paddle_mobile::PaddleMobile paddle_mobile(config); paddle_mobile.SetThreadNum(1); diff --git a/test/test_include.h b/test/test_include.h index 7f45d6e2c4d33d30264c1b07c1f4220ca9be2b4f..e3d31d32537c204ff3872ceb2482b8d6c1965cf7 100644 --- a/test/test_include.h +++ b/test/test_include.h @@ -20,6 +20,7 @@ limitations under the License. */ #include "./test_helper.h" #include "common/enforce.h" +#include "common/util.h" #include "common/log.h" #include "executor_for_test.h" #include "framework/ddim.h" diff --git a/tools/shell/merge.sh b/tools/shell/merge.sh new file mode 100644 index 0000000000000000000000000000000000000000..08c19d9286f57eae8a62ead711331b3fa07c1dd5 --- /dev/null +++ b/tools/shell/merge.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# Combined all static libaries in the current directory into a single static library +# It is hardcoded to use the i386, armv7, and armv7s architectures; this can easily be changed via the 'archs' variable at the top +# The script takes a single argument, which is the name of the final, combined library to be created. +# +# For example: +# => combine_static_libraries.sh combined-library +# +# Script by Evan Schoenberg, Regular Rate and Rhythm Software +# Thanks to Claudiu Ursache for his blog post at http://www.cvursache.com/2013/10/06/Combining-Multi-Arch-Binaries/ which detailed the technique automated by this script +##### +# $1 = Name of output archive +##### + +# archs=(i386 armv7 armv7s) +archs=(armv7 arm64) +libraries=(*.a) +libtool="/usr/bin/libtool" + +echo "Combining ${libraries[*]}..." + +for library in ${libraries[*]} +do + lipo -info $library + + # Extract individual architectures for this library + for arch in ${archs[*]} + do + lipo -extract $arch $library -o ${library}_${arch}.a + done +done + +# Combine results of the same architecture into a library for that architecture +source_combined="" +for arch in ${archs[*]} +do + source_libraries="" + + for library in ${libraries[*]} + do + source_libraries="${source_libraries} ${library}_${arch}.a" + done + + $libtool -static ${source_libraries} -o "${1}_${arch}.a" + source_combined="${source_combined} ${1}_${arch}.a" + + # Delete intermediate files + rm ${source_libraries} +done + +# Merge the combined library for each architecture into a single fat binary +lipo -create $source_combined -o $1.a + +# Delete intermediate files +rm ${source_combined} + +# Show info on the output library as confirmation +echo "Combination complete." +lipo -info $1.a