tvm_backend.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "ultra_infer/runtime/backends/tvm/tvm_backend.h"
  2. #include "yaml-cpp/yaml.h"
  3. namespace ultra_infer {
  4. bool TVMBackend::Init(const ultra_infer::RuntimeOption &runtime_option) {
  5. if (!(Supported(runtime_option.model_format, Backend::TVM) &&
  6. Supported(runtime_option.device, Backend::TVM))) {
  7. FDERROR << "TVMBackend only supports model "
  8. "ModelFormat::TVMFormat/Backend::TVM, but now its "
  9. << runtime_option.model_format << "/" << runtime_option.device
  10. << std::endl;
  11. return false;
  12. }
  13. if (runtime_option.model_from_memory_) {
  14. FDERROR << "TVMBackend doesn't support load model from memory, please "
  15. "load model from disk."
  16. << std::endl;
  17. return false;
  18. }
  19. if (!BuildDLDevice(runtime_option.device)) {
  20. FDERROR << "TVMBackend only don't support run in this device." << std::endl;
  21. return false;
  22. }
  23. if (!BuildModel(runtime_option)) {
  24. FDERROR << "TVMBackend only don't support run with this model path."
  25. << std::endl;
  26. return false;
  27. }
  28. if (!InitInputAndOutputTensor()) {
  29. FDERROR << "InitInputAndOutputTensor failed." << std::endl;
  30. return false;
  31. }
  32. return true;
  33. }
  34. bool TVMBackend::InitInputAndOutputTensor() {
  35. input_tensor_.resize(NumInputs());
  36. for (int i = 0; i < NumInputs(); ++i) {
  37. TensorInfo tensor_info = GetInputInfo(i);
  38. tvm::ShapeTuple shape(tensor_info.shape.begin(), tensor_info.shape.end());
  39. input_tensor_[i] = tvm::runtime::NDArray::Empty(
  40. shape, FDDataTypeToDLDataType(tensor_info.dtype), dev_);
  41. }
  42. output_tensor_.resize(NumOutputs());
  43. for (int i = 0; i < NumOutputs(); ++i) {
  44. TensorInfo tensor_info = GetOutputInfo(i);
  45. tvm::ShapeTuple shape(tensor_info.shape.begin(), tensor_info.shape.end());
  46. output_tensor_[i] = tvm::runtime::NDArray::Empty(
  47. shape, FDDataTypeToDLDataType(tensor_info.dtype), dev_);
  48. }
  49. return true;
  50. }
  51. bool TVMBackend::BuildModel(const RuntimeOption &runtime_option) {
  52. // load in the library
  53. tvm::runtime::Module mod_factory =
  54. tvm::runtime::Module::LoadFromFile(runtime_option.model_file);
  55. // create the graph executor module
  56. gmod_ = mod_factory.GetFunction("default")(dev_);
  57. // load params
  58. std::ifstream params_in(runtime_option.params_file, std::ios::binary);
  59. std::string params_data((std::istreambuf_iterator<char>(params_in)),
  60. std::istreambuf_iterator<char>());
  61. params_in.close();
  62. TVMByteArray params_arr;
  63. params_arr.data = params_data.c_str();
  64. params_arr.size = params_data.length();
  65. tvm::runtime::PackedFunc load_params = gmod_.GetFunction("load_params");
  66. load_params(params_arr);
  67. // read input and output info
  68. tvm::runtime::PackedFunc get_input_info = gmod_.GetFunction("get_input_info");
  69. tvm::Map<tvm::String, tvm::ObjectRef> input_info = get_input_info();
  70. auto input_info_shape = tvm::Downcast<tvm::Map<tvm::String, tvm::ShapeTuple>>(
  71. input_info["shape"]);
  72. inputs_desc_.reserve(input_info_shape.size());
  73. for (auto map_node : input_info_shape) {
  74. std::string temp_name = map_node.first;
  75. tvm::ShapeTuple tup = map_node.second;
  76. std::vector<int> temp_shape{};
  77. temp_shape.resize(tup.size());
  78. for (int j = 0; j < tup.size(); ++j) {
  79. temp_shape[j] = static_cast<int>(tup[j]);
  80. }
  81. FDDataType temp_dtype = ultra_infer::UNKNOWN1;
  82. TensorInfo temp_input_info = {temp_name, temp_shape, temp_dtype};
  83. inputs_desc_.emplace_back(temp_input_info);
  84. }
  85. int input_dtype_index = 0;
  86. auto input_info_dtype =
  87. tvm::Downcast<tvm::Map<tvm::String, tvm::String>>(input_info["dtype"]);
  88. for (auto map_node : input_info_dtype) {
  89. tvm::String tup = map_node.second;
  90. inputs_desc_[input_dtype_index].dtype = TVMTensorTypeToFDDataType(tup);
  91. input_dtype_index++;
  92. }
  93. tvm::runtime::PackedFunc get_output_info =
  94. gmod_.GetFunction("get_output_info");
  95. tvm::Map<tvm::String, tvm::ObjectRef> output_info = get_output_info();
  96. auto output_info_shape =
  97. tvm::Downcast<tvm::Map<tvm::String, tvm::ShapeTuple>>(
  98. output_info["shape"]);
  99. outputs_desc_.reserve(output_info_shape.size());
  100. for (auto map_node : output_info_shape) {
  101. std::string temp_name = map_node.first;
  102. tvm::ShapeTuple tup = map_node.second;
  103. std::vector<int> temp_shape{};
  104. temp_shape.resize(tup.size());
  105. for (int j = 0; j < tup.size(); ++j) {
  106. temp_shape[j] = static_cast<int>(tup[j]);
  107. }
  108. FDDataType temp_dtype = ultra_infer::FP32;
  109. TensorInfo temp_input_info = {temp_name, temp_shape, temp_dtype};
  110. outputs_desc_.emplace_back(temp_input_info);
  111. }
  112. int output_dtype_index = 0;
  113. auto output_info_dtype =
  114. tvm::Downcast<tvm::Map<tvm::String, tvm::String>>(output_info["dtype"]);
  115. for (auto map_node : output_info_dtype) {
  116. tvm::String tup = map_node.second;
  117. outputs_desc_[output_dtype_index].dtype = TVMTensorTypeToFDDataType(tup);
  118. output_dtype_index++;
  119. }
  120. return true;
  121. }
  122. FDDataType TVMBackend::TVMTensorTypeToFDDataType(tvm::String type) {
  123. if (type == "float32") {
  124. return FDDataType::FP32;
  125. }
  126. FDERROR << "FDDataType don't support this type" << std::endl;
  127. return FDDataType::UNKNOWN1;
  128. }
  129. bool TVMBackend::Infer(std::vector<FDTensor> &inputs,
  130. std::vector<FDTensor> *outputs, bool copy_to_fd) {
  131. for (int i = 0; i < inputs.size(); ++i) {
  132. memcpy(input_tensor_[i]->data, inputs[i].Data(), inputs[i].Nbytes());
  133. }
  134. // get the function from the module(set input data)
  135. tvm::runtime::PackedFunc set_input = gmod_.GetFunction("set_input");
  136. for (int i = 0; i < NumInputs(); ++i) {
  137. set_input(GetInputInfo(i).name, input_tensor_[i]);
  138. }
  139. // get the function from the module(run it)
  140. tvm::runtime::PackedFunc run = gmod_.GetFunction("run");
  141. run();
  142. // get the function from the module(get output data)
  143. tvm::runtime::PackedFunc get_output = gmod_.GetFunction("get_output");
  144. for (int i = 0; i < NumOutputs(); ++i) {
  145. get_output(i, output_tensor_[i]);
  146. }
  147. // get result
  148. outputs->resize(NumOutputs());
  149. std::vector<int64_t> temp_shape{};
  150. for (size_t i = 0; i < outputs_desc_.size(); ++i) {
  151. temp_shape.resize(outputs_desc_[i].shape.size());
  152. for (int j = 0; j < outputs_desc_[i].shape.size(); ++j) {
  153. temp_shape[j] = outputs_desc_[i].shape[j];
  154. }
  155. (*outputs)[i].Resize(temp_shape, outputs_desc_[i].dtype,
  156. outputs_desc_[i].name);
  157. memcpy((*outputs)[i].MutableData(),
  158. static_cast<float *>(output_tensor_[i]->data),
  159. (*outputs)[i].Nbytes());
  160. }
  161. return true;
  162. }
  163. bool TVMBackend::BuildDLDevice(ultra_infer::Device device) {
  164. if (device == Device::CPU) {
  165. dev_ = DLDevice{kDLCPU, 0};
  166. } else {
  167. FDERROR << "TVMBackend only support run in CPU." << std::endl;
  168. return false;
  169. }
  170. return true;
  171. }
  172. DLDataType TVMBackend::FDDataTypeToDLDataType(ultra_infer::FDDataType dtype) {
  173. if (dtype == FDDataType::FP32) {
  174. return DLDataType{kDLFloat, 32, 1};
  175. }
  176. return {};
  177. }
  178. } // namespace ultra_infer