#include #include "helpers/data_parser.h" #include "misc.h" #include "models/model_lite.h" #include "models/model_mdl.h" #include "io_options.h" namespace lar { template <> void InputOption::config_model_internel( RuntimeParam& runtime_param, std::shared_ptr model) { if (runtime_param.stage == RunStage::BEFORE_MODEL_LOAD) { auto&& parser = model->get_input_parser(); auto&& io = model->get_networkIO(); for (size_t idx = 0; idx < data_path.size(); ++idx) { parser.feed(data_path[idx].c_str()); } auto inputs = parser.inputs; bool is_host = true; for (auto& i : inputs) { io.inputs.push_back({i.first, is_host}); } } else if (runtime_param.stage == RunStage::AFTER_MODEL_LOAD) { auto&& parser = model->get_input_parser(); auto&& network = model->get_lite_network(); //! datd type map from lite data type to mgb data type std::map type_map = { {LiteDataType::LITE_FLOAT, megdnn::DTypeEnum::Float32}, {LiteDataType::LITE_INT, megdnn::DTypeEnum::Int32}, {LiteDataType::LITE_INT8, megdnn::DTypeEnum::Int8}, {LiteDataType::LITE_UINT8, megdnn::DTypeEnum::Uint8}}; if (m_force_batch_size > 0) { LITE_WARN("force set batch size to %d", m_force_batch_size); auto all_inputs_name = network->get_all_input_name(); for (auto& name : all_inputs_name) { std::shared_ptr input_tensor = network->get_io_tensor(name); //! set lite layout lite::Layout layout; mgb::TensorShape new_shape; new_shape.ndim = input_tensor->get_layout().ndim; layout.ndim = input_tensor->get_layout().ndim; for (size_t idx = 0; idx < new_shape.ndim; idx++) { new_shape.shape[idx] = input_tensor->get_layout().shapes[idx]; layout.shapes[idx] = new_shape.shape[idx]; } new_shape.shape[0] = m_force_batch_size; layout.shapes[0] = m_force_batch_size; //! gengrate tesnor copy from origin tensor mgb::HostTensorND hv; hv.comp_node(mgb::CompNode::default_cpu(), true) .dtype(megdnn::DType::from_enum( type_map[input_tensor->get_layout().data_type])) .resize(new_shape); mgb::dt_byte* raw_ptr = hv.raw_ptr(); //! single batch input size size_t batch_stride = hv.dtype().size() * hv.layout().total_nr_elems() / m_force_batch_size; size_t curr_batch_size = m_force_batch_size; //! copy data from origin input_tensor size_t init_batch = input_tensor->get_layout().shapes[0]; while (curr_batch_size > init_batch) { memcpy((char*)raw_ptr, (char*)(input_tensor->get_memory_ptr()), batch_stride * init_batch); curr_batch_size -= init_batch; raw_ptr += batch_stride * init_batch; } memcpy((char*)raw_ptr, (char*)(input_tensor->get_memory_ptr()), batch_stride * curr_batch_size); input_tensor->reset(hv.raw_ptr(), layout); parser.inputs[name] = std::move(hv); } } else { for (auto& i : parser.inputs) { //! get tensor information from data parser auto tensor = i.second; auto tensor_shape = tensor.shape(); mgb::dt_byte* src = tensor.raw_ptr(); std::shared_ptr input_tensor = network->get_io_tensor(i.first); //! set lite layout lite::Layout layout; layout.ndim = tensor_shape.ndim; for (size_t idx = 0; idx < tensor_shape.ndim; idx++) { layout.shapes[idx] = tensor_shape[idx]; } layout.data_type = input_tensor->get_layout().data_type; //! set data for only given shape if (tensor.storage().empty()) { mgb::HostTensorND hv; hv.comp_node(mgb::CompNode::default_cpu(), true) .dtype(megdnn::DType::from_enum(type_map[layout.data_type])) .resize(tensor.shape()); mgb::dt_byte* raw_ptr = hv.raw_ptr(); //! set all value in tesnor to 1 memset((char*)raw_ptr, 1, hv.layout().total_nr_elems() * hv.dtype().size()); parser.inputs[i.first] = std::move(hv); input_tensor->reset(raw_ptr, layout); } else { //! set network input tensor input_tensor->reset(src, layout); } } } } } template <> void InputOption::config_model_internel( RuntimeParam& runtime_param, std::shared_ptr model) { if (runtime_param.stage == RunStage::BEFORE_MODEL_LOAD) { auto&& parser = model->get_input_parser(); for (size_t idx = 0; idx < data_path.size(); ++idx) { parser.feed(data_path[idx].c_str()); } } else if (runtime_param.stage == RunStage::AFTER_MODEL_LOAD) { auto&& parser = model->get_input_parser(); auto&& network = model->get_mdl_load_result(); auto&& tensormap = network.tensor_map; if (m_force_batch_size > 0) { mgb_log_warn("force set batch size to %d", m_force_batch_size); for (auto& iter : tensormap) { auto& in = iter.second; mgb::HostTensorND hv; mgb::TensorShape new_shape = in->shape(); new_shape[0] = m_force_batch_size; hv.comp_node(mgb::CompNode::default_cpu(), true) .dtype(in->dtype()) .resize(new_shape); mgb::dt_byte* raw_ptr = hv.raw_ptr(); //! copy given batch data into new tensor size_t batch_stride = in->dtype().size() * in->layout().total_nr_elems() / (in->shape()[0]); size_t curr_batch_size = m_force_batch_size; //! copy data from origin input_tensor size_t init_batch = in->shape()[0]; while (curr_batch_size > init_batch) { memcpy((char*)raw_ptr, (char*)(in->raw_ptr()), batch_stride * init_batch); curr_batch_size -= init_batch; raw_ptr += batch_stride * init_batch; } memcpy((char*)raw_ptr, (char*)(in->raw_ptr()), batch_stride * curr_batch_size); //! set input tensor in->copy_from(hv); parser.inputs[iter.first] = std::move(hv); } } else { for (auto& i : parser.inputs) { mgb_assert( tensormap.find(i.first) != tensormap.end(), "can't find tesnor named %s", i.first.c_str()); auto& in = tensormap.find(i.first)->second; if (i.second.storage().empty()) { mgb::HostTensorND hv; hv.comp_node(mgb::CompNode::default_cpu(), true) .dtype(in->dtype()) .resize(i.second.shape()); mgb::dt_byte* raw_ptr = hv.raw_ptr(); memset((char*)raw_ptr, 1, hv.layout().total_nr_elems() * hv.dtype().size()); in->copy_from(hv); parser.inputs[i.first] = std::move(hv); } else { in->copy_from(i.second); } } } } } template <> void IOdumpOption::config_model_internel( RuntimeParam& runtime_param, std::shared_ptr model) { if (runtime_param.stage == RunStage::AFTER_MODEL_LOAD) { if (enable_io_dump) { LITE_LOG("enable text io dump"); lite::Runtime::enable_io_txt_dump(model->get_lite_network(), dump_path); } if (enable_bin_io_dump) { LITE_LOG("enable binary io dump"); lite::Runtime::enable_io_bin_dump(model->get_lite_network(), dump_path); } //! FIX:when add API in lite complate this if (enable_io_dump_stdout || enable_io_dump_stderr) { LITE_THROW("lite model don't support the stdout or stderr io dump"); } if (enable_bin_out_dump) { LITE_THROW("lite model don't support the binary output dump"); } if (enable_copy_to_host) { LITE_LOG("lite model set copy to host defaultly"); } } } template <> void IOdumpOption::config_model_internel( RuntimeParam& runtime_param, std::shared_ptr model) { if (runtime_param.stage == RunStage::BEFORE_MODEL_LOAD) { if (enable_io_dump) { mgb_log("enable text io dump"); auto iodump = std::make_unique( model->get_mdl_config().comp_graph.get(), dump_path.c_str()); iodump->print_addr(false); io_dumper = std::move(iodump); } if (enable_io_dump_stdout) { mgb_log("enable text io dump to stdout"); std::shared_ptr std_out(stdout, [](FILE*) {}); auto iodump = std::make_unique( model->get_mdl_config().comp_graph.get(), std_out); iodump->print_addr(false); io_dumper = std::move(iodump); } if (enable_io_dump_stderr) { mgb_log("enable text io dump to stderr"); std::shared_ptr std_err(stderr, [](FILE*) {}); auto iodump = std::make_unique( model->get_mdl_config().comp_graph.get(), std_err); iodump->print_addr(false); io_dumper = std::move(iodump); } if (enable_bin_io_dump) { mgb_log("enable binary io dump"); auto iodump = std::make_unique( model->get_mdl_config().comp_graph.get(), dump_path); io_dumper = std::move(iodump); } if (enable_bin_out_dump) { mgb_log("enable binary output dump"); out_dumper = std::make_unique(dump_path.c_str()); } } else if (runtime_param.stage == RunStage::AFTER_MODEL_LOAD) { if (enable_bin_out_dump) { auto&& load_result = model->get_mdl_load_result(); out_dumper->set(load_result.output_var_list); std::vector cb; for (size_t i = 0; i < load_result.output_var_list.size(); i++) { cb.push_back(out_dumper->bind()); } model->set_output_callback(cb); } if (enable_copy_to_host) { auto&& load_result = model->get_mdl_load_result(); std::vector cb; for (size_t i = 0; i < load_result.output_var_list.size(); i++) { mgb::HostTensorND val; auto callback = [val](const mgb::DeviceTensorND& dv) mutable { val.copy_from(dv); }; cb.push_back(callback); } model->set_output_callback(cb); } } else if (runtime_param.stage == RunStage::AFTER_RUNNING_WAIT) { if (enable_bin_out_dump) { out_dumper->write_to_file(); } } } } // namespace lar ////////////////////// Input options //////////////////////// using namespace lar; void InputOption::update() { data_path.clear(); m_option_name = "input"; size_t start = 0; auto end = FLAGS_input.find(";", start); while (end != std::string::npos) { std::string path = FLAGS_input.substr(start, end - start); data_path.emplace_back(path); start = end + 1; end = FLAGS_input.find(";", start); } data_path.emplace_back(FLAGS_input.substr(start)); m_force_batch_size = FLAGS_batch_size; } std::shared_ptr lar::InputOption::create_option() { static std::shared_ptr option(new InputOption); if (InputOption::is_valid()) { option->update(); return std::static_pointer_cast(option); } else { return nullptr; } } void InputOption::config_model( RuntimeParam& runtime_param, std::shared_ptr model) { CONFIG_MODEL_FUN; } ////////////////////// OprIOdump options //////////////////////// void IOdumpOption::update() { m_option_name = "iodump"; size_t valid_flag = 0; if (!FLAGS_io_dump.empty()) { dump_path = FLAGS_io_dump; enable_io_dump = true; valid_flag = valid_flag | (1 << 0); } if (!FLAGS_bin_io_dump.empty()) { dump_path = FLAGS_bin_io_dump; enable_bin_io_dump = true; valid_flag = valid_flag | (1 << 1); } if (!FLAGS_bin_out_dump.empty()) { dump_path = FLAGS_bin_out_dump; enable_bin_out_dump = true; valid_flag = valid_flag | (1 << 2); } if (FLAGS_io_dump_stdout) { enable_io_dump_stdout = FLAGS_io_dump_stdout; valid_flag = valid_flag | (1 << 3); } if (FLAGS_io_dump_stderr) { enable_io_dump_stderr = FLAGS_io_dump_stderr; valid_flag = valid_flag | (1 << 4); } // not only one dump set valid if (valid_flag && (valid_flag & (valid_flag - 1))) { mgb_log_warn( "ONLY the last io dump option is validate and others is " "skipped!!!"); } enable_copy_to_host = FLAGS_copy_to_host; } bool IOdumpOption::is_valid() { bool ret = !FLAGS_io_dump.empty(); ret = ret || FLAGS_io_dump_stdout; ret = ret || FLAGS_io_dump_stderr; ret = ret || !FLAGS_bin_io_dump.empty(); ret = ret || !FLAGS_bin_out_dump.empty(); ret = ret || FLAGS_copy_to_host; return ret; } std::shared_ptr IOdumpOption::create_option() { static std::shared_ptr option(new IOdumpOption); if (IOdumpOption::is_valid()) { option->update(); return std::static_pointer_cast(option); } else { return nullptr; } } void IOdumpOption::config_model( RuntimeParam& runtime_param, std::shared_ptr model) { CONFIG_MODEL_FUN; } ////////////////////// Input gflags //////////////////////// DEFINE_string( input, "", "Set up inputs data for model --input [ file_path | data_string]"); DEFINE_int32( batch_size, -1, "set the batch size of input(especially for global layout transform " "optimization working on)"); ////////////////////// OprIOdump gflags //////////////////////// DEFINE_string(io_dump, "", "set the io dump file path in text format"); DEFINE_bool(io_dump_stdout, false, "dump io opr to stdout in text format"); DEFINE_bool(io_dump_stderr, false, "dump io opr to stderr in text format"); DEFINE_string( bin_io_dump, "", "set the io dump directory path where variable in binary format located"); DEFINE_string( bin_out_dump, "", "set the out dump directory path where output variable in binary format " "located"); DEFINE_bool(copy_to_host, false, "copy device data to host"); REGIST_OPTION_CREATOR(input, lar::InputOption::create_option); REGIST_OPTION_CREATOR(iodump, lar::IOdumpOption::create_option);