Caffe2 - C++ API
A deep learning, cross platform ML framework
backend_transformer_base.cc
1 #include "caffe2/opt/backend_transformer_base.h"
2 #include "caffe2/onnx/onnx_exporter.h"
3 #include "caffe2/utils/proto_utils.h"
4 
5 namespace caffe2 {
6 
7 namespace {
8 void annotateOpIndex(NetDef* net) {
9  int i = 0;
10  for (auto& op : *(net->mutable_op())) {
11  AddArgument(kNetPos, i++, &op);
12  }
13 }
14 } // namespace
15 
16 std::string BackendTransformerBase::getModelId(const NetDef& net) {
17  static std::atomic<size_t> seq_id{0};
18  std::string model_id;
19  for (const auto& arg : net.arg()) {
20  if (arg.name() == kModelId) {
21  if (arg.has_s()) {
22  model_id = arg.s();
23  } else if (arg.has_i()) {
24  model_id = c10::to_string(arg.i());
25  }
26  break;
27  }
28  }
29 
30  if (model_id.empty()) {
31  model_id = "unnamed_" + c10::to_string(seq_id++);
32  }
33  return model_id;
34 }
35 
36 TensorProto BackendTransformerBase::wrapShapeInfoIntoTensorProto(
37  const std::string& name,
38  const ShapeInfo& shape_info) const {
39  TensorProto t;
40  t.set_name(name);
41  t.set_data_type(shape_info.shape.data_type());
42  for (const auto i : shape_info.shape.dims()) {
43  t.add_dims(i);
44  }
45  return t;
46 }
47 
48 std::unordered_map<std::string, TensorShape>
49 BackendTransformerBase::ssaRewriteAndMapNames(
50  Workspace* ws,
51  NetDef* pred_net,
52  const std::unordered_map<std::string, TensorShape>& input_shape_hints) {
53  input_mapping_ = onnx::SsaRewrite(nullptr, pred_net);
54  // Annote the ops with net position
55  annotateOpIndex(pred_net);
56 
57  // Since we are going to create a mapped workspace, we need to make sure that
58  // the parent workspace has the mapped blob names. If the blobs don't exist
59  // (usually such blobs are input tensor names), we exclude them from mapping.
60  std::vector<std::string> exclude_mapping;
61  for (const auto kv : input_mapping_) {
62  if (!ws->HasBlob(kv.second)) {
63  exclude_mapping.emplace_back(kv.first);
64  }
65  }
66  for (const auto& i : exclude_mapping) {
67  input_mapping_.erase(i);
68  }
69 
70  std::unordered_map<std::string, TensorShape> shape_hints_mapped;
71  for (const auto& kv : input_shape_hints) {
72  shape_hints_mapped.emplace(kv.first, kv.second);
73  }
74  return shape_hints_mapped;
75 }
76 
77 ShapeInfoMap BackendTransformerBase::inferShapes(
78  Workspace* ws,
79  NetDef* pred_net,
80  const std::unordered_map<std::string, TensorShape>& shape_hints_mapped,
81  const BoundShapeSpec& spec) {
82  ShapeInfoMap shape_map;
83  // Populate shapes from workplace
84  const std::vector<std::string> ws_blobs = ws->Blobs();
85  for (const auto& s : ws_blobs) {
86  auto shape_info = getShapeInfoFromBlob(ws->GetBlob(s));
87  if (shape_info.dim_type != ShapeInfo::DimType::UNKNOWN) {
88  shape_map[s] = shape_info;
89  }
90  }
91  // We treat hinted shapes as BATCH. If there are shape hints on blobs in the
92  // workspace, since they are already inserted as CONSTANT, it will take effect
93  // here. For SEQ typed tensors, there are only a few of them and they will be
94  // handled by BoundShapeInferencer.
95  for (const auto& kv : shape_hints_mapped) {
96  shape_map.emplace(
97  std::piecewise_construct,
98  std::forward_as_tuple(kv.first),
99  std::forward_as_tuple(ShapeInfo::DimType::BATCH, kv.second));
100  }
101  BoundShapeInferencer eng(spec);
102  eng.InferBoundShapeAndType(*pred_net, shape_map);
103  const auto& out_map = eng.shape_info();
104  shape_map.clear();
105  for (const auto& kv : out_map) {
106  shape_map.emplace(
107  std::piecewise_construct,
108  std::forward_as_tuple(kv.first),
109  std::forward_as_tuple(kv.second.dim_type, kv.second.shape));
110  }
111  return shape_map;
112 }
113 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13