Caffe2 - C++ API
A deep learning, cross platform ML framework
copy_op.cc
1 #include "caffe2/operators/copy_op.h"
2 
3 namespace caffe2 {
4 
5 // From CPU, copy it to whatever the current context
6 REGISTER_CPU_OPERATOR(
7  CopyFromCPUInput,
8  CopyOp<CPUContext, CPUContext, CPUContext>);
9 REGISTER_CPU_OPERATOR(
10  CopyOnDeviceLike,
11  CopyOnDeviceLikeOp<CPUContext, CPUContext, CPUContext>);
12 REGISTER_CPU_OPERATOR(Copy, CopyOp<CPUContext, CPUContext, CPUContext>);
13 
14 OPERATOR_SCHEMA(Copy)
15  .NumInputs(1)
16  .NumOutputs(1)
17  .IdenticalTypeAndShape()
18  .InputsCanCrossDevices()
19  .SetDoc(R"DOC(
20 Copy input tensor into output, potentially across devices.
21 
22 Github Links:
23 
24 - https://github.com/caffe2/caffe2/blob/master/caffe2/operators/copy_op.cc
25 - https://github.com/caffe2/caffe2/blob/master/caffe2/operators/copy_op.h
26 
27 
28 <details>
29 
30 <summary> <b>Example</b> </summary>
31 
32 **Code**
33 
34 ```
35 
36 workspace.ResetWorkspace()
37 
38 op = core.CreateOperator(
39  "Copy",
40  ["input"],
41  ["output"]
42 )
43 
44 workspace.FeedBlob("input", np.random.rand(3,3))
45 print("input:", workspace.FetchBlob("input"))
46 workspace.RunOperatorOnce(op)
47 print("output:", workspace.FetchBlob("output"))
48 
49 ```
50 
51 **Result**
52 
53 ```
54 
55 input:
56 [[0.16826761 0.68168217 0.55196001]
57  [0.19735483 0.34837823 0.69015595]
58  [0.09448514 0.57390828 0.37097193]]
59 output:
60 [[0.16826761 0.68168217 0.55196001]
61  [0.19735483 0.34837823 0.69015595]
62  [0.09448514 0.57390828 0.37097193]]
63 
64 ```
65 
66 </details>
67 
68 )DOC")
69  .Input(0, "input", "(*Tensor*): input tensor to copy")
70  .Output(0, "output", "(*Tensor*): copy of input tensor");
71 
72 OPERATOR_SCHEMA(CopyGPUToCPU)
73  .NumInputs(1)
74  .NumOutputs(1)
75  .IdenticalTypeAndShape()
76  .InputsCanCrossDevices()
77  .DeviceInferenceFunction([](const OperatorDef& def) {
78  CAFFE_ENFORCE(
79  def.has_device_option(),
80  "CopyGPUToCPU op should have cuda device option.");
81  auto& cuda_option = def.device_option();
82  auto cpu_option = DeviceOption();
83  vector<DeviceOption> in_dev(def.input_size(), cuda_option);
84  vector<DeviceOption> out_dev(def.output_size(), cpu_option);
85  return std::make_pair(in_dev, out_dev);
86  })
87  .SetDoc(R"DOC(
88 Copy tensor for GPU to CPU context. Must be run under GPU device option.
89 )DOC")
90  .Input(0, "input", "The input tensor.")
91  .Output(0, "output", "Tensor that will contain a copy of the input.");
92 
93 OPERATOR_SCHEMA(CopyCPUToGPU)
94  .NumInputs(1)
95  .NumOutputs(1)
96  .IdenticalTypeAndShape()
97  .InputsCanCrossDevices()
98  .DeviceInferenceFunction([](const OperatorDef& def) {
99  CAFFE_ENFORCE(
100  def.has_device_option(),
101  "CopyCPUToGPU op should have cuda device option.");
102  auto& cuda_option = def.device_option();
103  auto cpu_option = DeviceOption();
104  vector<DeviceOption> in_dev(def.input_size(), cpu_option);
105  vector<DeviceOption> out_dev(def.output_size(), cuda_option);
106  return std::make_pair(in_dev, out_dev);
107  })
108  .SetDoc(R"DOC(
109 Copy tensor for CPU to GPU context. Must be run under GPU device option.
110 )DOC")
111  .Input(0, "input", "The input tensor.")
112  .Output(0, "output", "Tensor that will contain a copy of the input.");
113 
114 OPERATOR_SCHEMA(CopyFromCPUInput)
115  .NumInputs(1)
116  .NumOutputs(1)
117  .IdenticalTypeAndShape()
118  .InputsCanCrossDevices()
119  .DeviceInferenceFunction([](const OperatorDef& def) {
120  auto op_device =
121  def.has_device_option() ? def.device_option() : DeviceOption();
122  auto cpu_option = DeviceOption();
123  vector<DeviceOption> in_dev(def.input_size(), cpu_option);
124  vector<DeviceOption> out_dev(def.output_size(), op_device);
125  return std::make_pair(in_dev, out_dev);
126  })
127  .SetDoc(R"DOC(
128 Take a CPU input tensor and copy it to an output in the current
129 Context (GPU or CPU). This may involves cross-device MemCpy.
130 )DOC")
131  .Input(0, "input", "The input CPU tensor.")
132  .Output(0, "output", "either a TensorCUDA or a TensorCPU");
133 
134 OPERATOR_SCHEMA(CopyOnDeviceLike)
135  .NumInputs(2)
136  .NumOutputs(1)
137  .SetDoc("Copy input tensor into output to the specific device.")
138  .Input(0, "input", "The input tensor.")
139  .Input(1, "dst", "Tensor, on which device the copy will be performed.")
140  .Output(0, "output", "Tensor that will contain a copy of the input.");
141 
142 struct GetCopyGradient : public GradientMakerBase {
143  using GradientMakerBase::GradientMakerBase;
144  vector<OperatorDef> GetGradientDefs() override {
145  return SingleGradientDef(
146  "CopyOnDeviceLike",
147  "",
148  vector<string>{GO(0), I(0)},
149  vector<string>{GI(0)});
150  }
151 };
152 REGISTER_GRADIENT(Copy, GetCopyGradient);
153 
154 struct GetGPUToCPUGradient : public GradientMakerBase {
155  using GradientMakerBase::GradientMakerBase;
156  vector<OperatorDef> GetGradientDefs() override {
157  if (g_output_[0].IsDense()) {
158  return SingleGradientDef(
159  "CopyCPUToGPU", "", vector<string>{GO(0)}, vector<string>{GI(0)});
160  } else {
161  return vector<OperatorDef>{CreateOperatorDef(
162  "CopyCPUToGPU",
163  "",
164  std::vector<string>{GO_I(0)},
165  std::vector<string>{GI_I(0)}),
166  CreateOperatorDef(
167  "CopyCPUToGPU",
168  "",
169  std::vector<string>{GO_V(0)},
170  std::vector<string>{GI_V(0)})};
171  }
172  }
173 };
174 REGISTER_GRADIENT(CopyGPUToCPU, GetGPUToCPUGradient);
175 
176 struct GetCPUToGPUGradient : public GradientMakerBase {
177  using GradientMakerBase::GradientMakerBase;
178  vector<OperatorDef> GetGradientDefs() override {
179  if (g_output_[0].IsDense()) {
180  return SingleGradientDef(
181  "CopyGPUToCPU", "", vector<string>{GO(0)}, vector<string>{GI(0)});
182  } else {
183  return vector<OperatorDef>{CreateOperatorDef(
184  "CopyGPUToCPU",
185  "",
186  std::vector<string>{GO_I(0)},
187  std::vector<string>{GI_I(0)}),
188  CreateOperatorDef(
189  "CopyGPUToCPU",
190  "",
191  std::vector<string>{GO_V(0)},
192  std::vector<string>{GI_V(0)})};
193  }
194  }
195 };
196 REGISTER_GRADIENT(CopyCPUToGPU, GetCPUToGPUGradient);
197 
198 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13
static vector< OperatorDef > SingleGradientDef(const Args &...args)
a helper function to allow one to create one single operator def, which is usually the case for many ...