Caffe2 - C++ API
A deep learning, cross platform ML framework
tensor.cc
1 #include "caffe2/core/tensor.h"
2 
3 #include "caffe2/core/blob_stats.h"
4 #include "caffe2/core/flags.h"
5 
6 CAFFE2_DEFINE_bool(
7  caffe2_keep_on_shrink,
8  true,
9  "If set, keeps memory when a tensor is shrinking its size.");
10 
11 namespace caffe2 {
12 // declaring it here instead of context.cc because tensor.h includes context.h
13 CAFFE_KNOWN_TYPE(Tensor<CPUContext>);
14 
15 TensorPrinter::TensorPrinter(
16  const std::string& tensor_name,
17  const std::string& file_name,
18  int limit)
19  : to_file_(!file_name.empty()),
20  limit_(limit ? limit : k_limit_default_),
21  tensor_name_(tensor_name) {
22  if (to_file_) {
23  // We will output to file instead of printing on screen.
24  // We will write each individual tensor to its individual file.
25  log_file_.reset(new std::ofstream(
26  file_name, std::ofstream::out | std::ofstream::trunc));
27  CAFFE_ENFORCE(
28  log_file_->good(),
29  "Failed to open TensorPrinter file ",
30  file_name,
31  ". rdstate() = ",
32  log_file_->rdstate());
33  }
34 }
35 
36 TensorPrinter::~TensorPrinter() {
37  if (log_file_.get()) {
38  log_file_->close();
39  }
40 }
41 
42 std::string TensorPrinter::MetaStr(const Tensor<CPUContext>& tensor) {
43  std::stringstream meta_stream;
44  meta_stream << "Tensor " << tensor_name_ << " of type "
45  << tensor.meta().name() << ". Dims: (";
46  for (const auto dim : tensor.dims()) {
47  meta_stream << dim << ",";
48  }
49  meta_stream << "): ";
50  return meta_stream.str();
51 }
52 
53 static CaffeMap<CaffeTypeId, TypeCall> type_call_registry_ {
54  {TypeMeta::Id<Tensor<CPUContext>>(), GetTensorType<Tensor<CPUContext>>}
55 };
56 
57 TypeCall GetTypeCallFunction(CaffeTypeId id) {
58  auto f = type_call_registry_.find(id);
59  if (f == type_call_registry_.end()) {
60  return nullptr;
61  }
62  return f->second;
63 }
64 
65 void RegisterTypeCallFunction(CaffeTypeId id, TypeCall c) {
66  type_call_registry_[id] = c;
67 }
68 
69 static CaffeMap<CaffeTypeId, ShapeCall> shape_call_registry_ {
70  {TypeMeta::Id<Tensor<CPUContext>>(), GetTensorShape<Tensor<CPUContext>>}
71 };
72 
73 ShapeCall GetShapeCallFunction(CaffeTypeId id) {
74  auto f = shape_call_registry_.find(id);
75  if (f == shape_call_registry_.end()) {
76  return nullptr;
77  }
78  return f->second;
79 }
80 
81 void RegisterShapeCallFunction(CaffeTypeId id, ShapeCall c) {
82  shape_call_registry_[id] = c;
83 }
84 
85 namespace {
86 
87 struct TensorCPUStatGetter : BlobStatGetter {
88  size_t sizeBytes(const Blob& blob) const override {
89  const auto& tensor = blob.Get<TensorCPU>();
90  auto nbytes = tensor.nbytes();
91  if (nbytes > 0 && tensor.IsType<std::string>()) {
92  const auto* data = tensor.data<std::string>();
93  for (size_t i = 0; i < tensor.size(); ++i) {
94  nbytes += data[i].size();
95  }
96  }
97  return nbytes;
98  }
99 };
100 REGISTER_BLOB_STAT_GETTER(TensorCPU, TensorCPUStatGetter);
101 }
102 
103 } // namespace caffe2
Simple registry implementation in Caffe2 that uses static variables to register object creators durin...
Commandline flags support for Caffe2.