Caffe2 - C++ API
A deep learning, cross platform ML framework
context.h
1 #ifndef CAFFE2_CORE_CONTEXT_H_
2 #define CAFFE2_CORE_CONTEXT_H_
3 
4 #include <cstdlib>
5 #include <ctime>
6 #include <random>
7 #include <unordered_map>
8 
9 #include "caffe2/core/allocator.h"
10 #include "caffe2/core/context_base.h"
11 #include "caffe2/core/event.h"
12 #include "caffe2/core/logging.h"
13 #include <c10/util/typeid.h>
14 #include "caffe2/proto/caffe2_pb.h"
15 
16 #include <c10/util/ArrayRef.h>
17 
18 C10_DECLARE_bool(caffe2_report_cpu_memory_usage);
19 
20 namespace caffe2 {
21 
26 CAFFE2_API uint32_t RandomNumberSeed();
27 
40 class CAFFE2_API CPUContext final : public BaseContext {
41  public:
42  typedef std::mt19937 rand_gen_type;
43  CPUContext() : random_seed_(RandomNumberSeed()) {}
44  explicit CPUContext(const DeviceOption& option)
45  : random_seed_(
46  option.has_random_seed() ? option.random_seed()
47  : RandomNumberSeed()) {
48  CAFFE_ENFORCE_EQ(option.device_type(), PROTO_CPU);
49  }
50  explicit CPUContext(const at::Device& device)
51  : CPUContext(DeviceToOption(device)) {}
52 
53  ~CPUContext() noexcept override {}
54 
55  inline void SwitchToDevice(int /*stream_id*/) override {}
56 
57  using BaseContext::SwitchToDevice;
58 
59  inline void WaitEvent(const Event& ev) override {
60  ev.Wait(CPU, this);
61  }
62 
63  inline void Record(Event* ev, const char* err_msg = nullptr) const override {
64  CAFFE_ENFORCE(ev, "Event must not be null.");
65  ev->Record(CPU, this, err_msg);
66  }
67 
68  inline void FinishDeviceComputation() override {}
69 
70  inline rand_gen_type& RandGenerator() {
71  if (!random_generator_.get()) {
72  random_generator_.reset(new rand_gen_type(random_seed_));
73  }
74  return *random_generator_.get();
75  }
76 
77  inline static at::DataPtr New(size_t nbytes) {
78  return GetCPUAllocator()->allocate(nbytes);
79  }
80 
81  void CopyBytesSameDevice(size_t nbytes, const void* src, void* dst) override;
82 
83  void CopyBytesFromCPU(size_t nbytes, const void* src, void* dst) override {
84  CopyBytesSameDevice(nbytes, src, dst);
85  }
86 
87  void CopyBytesToCPU(size_t nbytes, const void* src, void* dst) override {
88  CopyBytesSameDevice(nbytes, src, dst);
89  }
90 
91  bool SupportsNonFundamentalTypes() const override {
92  // CPU non fumdamental type copy OK
93  return true;
94  }
95 
96  template <class SrcContext, class DstContext>
97  inline void CopyBytes(size_t nbytes, const void* src, void* dst);
98 
99  template <typename T, class SrcContext, class DstContext>
100  inline void Copy(size_t n, const T* src, T* dst) {
101  if (std::is_fundamental<T>::value) {
102  CopyBytes<SrcContext, DstContext>(
103  n * sizeof(T),
104  static_cast<const void*>(src),
105  static_cast<void*>(dst));
106  } else {
107  for (size_t i = 0; i < n; ++i) {
108  dst[i] = src[i];
109  }
110  }
111  }
112 
113  template <class SrcContext, class DstContext>
114  inline void
115  CopyItems(const TypeMeta& meta, size_t n, const void* src, void* dst) {
116  if (meta.copy()) {
117  meta.copy()(src, dst, n);
118  } else {
119  CopyBytes<SrcContext, DstContext>(n * meta.itemsize(), src, dst);
120  }
121  }
122 
123  // By default CPU operators don't have async device parts
124  static bool HasAsyncPartDefault() {
125  return false;
126  }
127 
128  static bool SupportsAsyncScheduling() {
129  return false;
130  }
131 
132  // CPU streams are not implemented and are silently ignored by CPU ops,
133  // return true to signal executor to schedule a CPU op
134  static bool IsStreamFree(
135  const DeviceOption& /* option */,
136  int /* stream_id */) {
137  return true;
138  }
139 
140  at::Device device() const override {
141  // TODO: numa?
142  return at::Device(CPU);
143  }
144 
145  DeviceType device_type() const override {
146  return CPU;
147  }
148 
149  static constexpr DeviceType GetDeviceType() {
150  return CPU;
151  }
152 
153  protected:
154  // TODO(jiayq): instead of hard-coding a generator, make it more flexible.
155  int random_seed_{1701};
156  std::unique_ptr<rand_gen_type> random_generator_;
157 };
158 
159 template <>
160 inline void CPUContext::CopyBytes<CPUContext, CPUContext>(
161  size_t nbytes,
162  const void* src,
163  void* dst) {
164  if (nbytes == 0) {
165  return;
166  }
167  CAFFE_ENFORCE(src);
168  CAFFE_ENFORCE(dst);
169  memcpy(dst, src, nbytes);
170 }
171 
172 } // namespace caffe2
173 
174 #endif // CAFFE2_CORE_CONTEXT_H_
constexpr size_t itemsize() const noexcept
Returns the size of the item.
Definition: typeid.h:365
The CPU Context, representing the bare minimum of what a Context class in Caffe2 should implement...
Definition: context.h:40
Represents a a compute device on which a tensor is located.
Definition: Device.h:30
uint32_t RandomNumberSeed()
A function to generate a random number seed that is unique in a best-effort basis, using an ever-incrementing seed and the current time.
Definition: context.cc:10
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13
constexpr Copy * copy() const noexcept
Returns the typed copy function pointer for individual iterms.
Definition: typeid.h:380
TypeMeta is a thin class that allows us to store the type of a container such as a blob...
Definition: typeid.h:324