Caffe2 - C++ API
A deep learning, cross platform ML framework
workspace.h
1 #ifndef CAFFE2_CORE_WORKSPACE_H_
2 #define CAFFE2_CORE_WORKSPACE_H_
3 
4 #include "caffe2/core/common.h"
5 #include "caffe2/core/observer.h"
6 
7 #include <climits>
8 #include <cstddef>
9 #include <mutex>
10 #include <typeinfo>
11 #include <unordered_set>
12 #include <vector>
13 
14 #include "c10/util/Registry.h"
15 #include "caffe2/core/blob.h"
16 #include "caffe2/core/net.h"
17 #include "caffe2/proto/caffe2_pb.h"
18 #include "caffe2/utils/signal_handler.h"
19 #include "caffe2/utils/threadpool/ThreadPool.h"
20 
21 C10_DECLARE_bool(caffe2_print_blob_sizes_at_exit);
22 
23 namespace caffe2 {
24 
25 class NetBase;
26 
27 struct CAFFE2_API StopOnSignal {
28  StopOnSignal()
29  : handler_(std::make_shared<SignalHandler>(
30  SignalHandler::Action::STOP,
31  SignalHandler::Action::STOP)) {}
32 
33  StopOnSignal(const StopOnSignal& other) : handler_(other.handler_) {}
34 
35  bool operator()(int /*iter*/) {
36  return handler_->CheckForSignals() != SignalHandler::Action::STOP;
37  }
38 
39  std::shared_ptr<SignalHandler> handler_;
40 };
41 
47 class CAFFE2_API Workspace {
48  public:
49  typedef std::function<bool(int)> ShouldContinue;
50  typedef CaffeMap<string, unique_ptr<Blob> > BlobMap;
51  typedef CaffeMap<string, unique_ptr<NetBase> > NetMap;
55  Workspace() : Workspace(".", nullptr) {}
56 
64  explicit Workspace(const string& root_folder)
65  : Workspace(root_folder, nullptr) {}
66 
76  explicit Workspace(const Workspace* shared) : Workspace(".", shared) {}
77 
84  const Workspace* shared,
85  const std::unordered_map<string, string>& forwarded_blobs)
86  : Workspace(".", nullptr) {
87  CAFFE_ENFORCE(shared, "Parent workspace must be specified");
88  for (const auto& forwarded : forwarded_blobs) {
89  CAFFE_ENFORCE(
90  shared->HasBlob(forwarded.second),
91  "Invalid parent workspace blob: ",
92  forwarded.second);
93  forwarded_blobs_[forwarded.first] =
94  std::make_pair(shared, forwarded.second);
95  }
96  }
97 
101  Workspace(const string& root_folder, const Workspace* shared)
102  : root_folder_(root_folder), shared_(shared), bookkeeper_(bookkeeper()) {
103  std::lock_guard<std::mutex> guard(bookkeeper_->wsmutex);
104  bookkeeper_->workspaces.insert(this);
105  }
106 
107  ~Workspace() {
108  if (FLAGS_caffe2_print_blob_sizes_at_exit) {
109  PrintBlobSizes();
110  }
111  // This is why we have a bookkeeper_ shared_ptr instead of a naked static! A
112  // naked static makes us vulnerable to out-of-order static destructor bugs.
113  std::lock_guard<std::mutex> guard(bookkeeper_->wsmutex);
114  bookkeeper_->workspaces.erase(this);
115  }
116 
127  void AddBlobMapping(
128  const Workspace* parent,
129  const std::unordered_map<string, string>& forwarded_blobs,
130  bool skip_defined_blobs = false);
131 
136  template <class Context>
137  void CopyForwardedTensors(const std::unordered_set<std::string>& blobs) {
138  for (const auto& blob : blobs) {
139  if (!forwarded_blobs_.count(blob)) {
140  continue;
141  }
142  const auto& ws_blob = forwarded_blobs_[blob];
143  const auto* parent_ws = ws_blob.first;
144  auto* from_blob = parent_ws->GetBlob(ws_blob.second);
145  CAFFE_ENFORCE(from_blob);
146  CAFFE_ENFORCE(
147  from_blob->template IsType<Tensor>(),
148  "Expected blob with tensor value",
149  ws_blob.second);
150  forwarded_blobs_.erase(blob);
151  auto* to_blob = CreateBlob(blob);
152  CAFFE_ENFORCE(to_blob);
153  const auto& from_tensor = from_blob->template Get<Tensor>();
154  auto* to_tensor = BlobGetMutableTensor(to_blob, Context::GetDeviceType());
155  to_tensor->CopyFrom(from_tensor);
156  }
157  }
158 
163  vector<string> LocalBlobs() const;
164 
170  vector<string> Blobs() const;
171 
175  const string& RootFolder() { return root_folder_; }
179  inline bool HasBlob(const string& name) const {
180  // First, check the local workspace,
181  // Then, check the forwarding map, then the parent workspace
182  if (blob_map_.count(name)) {
183  return true;
184  } else if (forwarded_blobs_.count(name)) {
185  const auto parent_ws = forwarded_blobs_.at(name).first;
186  const auto& parent_name = forwarded_blobs_.at(name).second;
187  return parent_ws->HasBlob(parent_name);
188  } else if (shared_) {
189  return shared_->HasBlob(name);
190  }
191  return false;
192  }
193 
194  void PrintBlobSizes();
195 
201  Blob* CreateBlob(const string& name);
209  Blob* CreateLocalBlob(const string& name);
215  bool RemoveBlob(const string& name);
220  const Blob* GetBlob(const string& name) const;
225  Blob* GetBlob(const string& name);
226 
232  Blob* RenameBlob(const string& old_name, const string& new_name);
233 
243  NetBase* CreateNet(const NetDef& net_def, bool overwrite = false);
245  const std::shared_ptr<const NetDef>& net_def,
246  bool overwrite = false);
251  NetBase* GetNet(const string& net_name);
255  void DeleteNet(const string& net_name);
261  bool RunNet(const string& net_name);
262 
266  vector<string> Nets() const {
267  vector<string> names;
268  for (auto& entry : net_map_) {
269  names.push_back(entry.first);
270  }
271  return names;
272  }
273 
277  bool RunPlan(const PlanDef& plan_def,
278  ShouldContinue should_continue = StopOnSignal{});
279 
280  /*
281  * Returns a CPU threadpool instace for parallel execution of
282  * work. The threadpool is created lazily; if no operators use it,
283  * then no threadpool will be created.
284  */
285  ThreadPool* GetThreadPool();
286 
287  // RunOperatorOnce and RunNetOnce runs an operator or net once. The difference
288  // between RunNet and RunNetOnce lies in the fact that RunNet allows you to
289  // have a persistent net object, while RunNetOnce creates a net and discards
290  // it on the fly - this may make things like database read and random number
291  // generators repeat the same thing over multiple calls.
292  bool RunOperatorOnce(const OperatorDef& op_def);
293  bool RunNetOnce(const NetDef& net_def);
294 
301  template <typename F>
302  static void ForEach(F f) {
303  auto bk = bookkeeper();
304  std::lock_guard<std::mutex> guard(bk->wsmutex);
305  for (Workspace* ws : bk->workspaces) {
306  f(ws);
307  }
308  }
309 
310  public:
311  std::atomic<int> last_failed_op_net_position{};
312 
313  private:
314  struct Bookkeeper {
315  std::mutex wsmutex;
316  std::unordered_set<Workspace*> workspaces;
317  };
318 
319  static std::shared_ptr<Bookkeeper> bookkeeper();
320 
321  BlobMap blob_map_;
322  NetMap net_map_;
323  const string root_folder_;
324  const Workspace* shared_;
325  std::unordered_map<string, std::pair<const Workspace*, string>>
326  forwarded_blobs_;
327  std::unique_ptr<ThreadPool> thread_pool_;
328  std::mutex thread_pool_creation_mutex_;
329  std::shared_ptr<Bookkeeper> bookkeeper_;
330 
331  C10_DISABLE_COPY_AND_ASSIGN(Workspace);
332 };
333 
334 } // namespace caffe2
335 
336 #endif // CAFFE2_CORE_WORKSPACE_H_
const string & RootFolder()
Return the root folder of the workspace.
Definition: workspace.h:175
Blob is a general container that hosts a typed pointer.
Definition: blob.h:24
Workspace(const Workspace *shared, const std::unordered_map< string, string > &forwarded_blobs)
Initializes workspace with parent workspace, blob name remapping (new name -> parent blob name)...
Definition: workspace.h:83
Workspace(const Workspace *shared)
Initializes a workspace with a shared workspace.
Definition: workspace.h:76
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
static void ForEach(F f)
Applies a function f on each workspace that currently exists.
Definition: workspace.h:302
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13
Workspace(const string &root_folder)
Initializes an empty workspace with the given root folder.
Definition: workspace.h:64
bool HasBlob(const string &name) const
Checks if a blob with the given name is present in the current workspace.
Definition: workspace.h:179
unique_ptr< NetBase > CreateNet(const NetDef &net_def, Workspace *ws)
Creates a network, accessing / creating blobs in the given workspace.
Definition: net.cc:151
void CopyForwardedTensors(const std::unordered_set< std::string > &blobs)
Converts previously mapped tensor blobs to local blobs, copies values from parent workspace blobs int...
Definition: workspace.h:137
vector< string > Nets() const
Returns a list of names of the currently instantiated networks.
Definition: workspace.h:266
Workspace()
Initializes an empty workspace.
Definition: workspace.h:55
Workspace(const string &root_folder, const Workspace *shared)
Initializes a workspace with a root folder and a shared workspace.
Definition: workspace.h:101