Caffe2 - C++ API
A deep learning, cross platform ML framework
lengths_tile_op.cc
1 #include "caffe2/operators/lengths_tile_op.h"
2 
3 namespace caffe2 {
4 
5 template <>
6 bool LengthsTileOp<CPUContext>::RunOnDevice() {
7  auto& data = Input(DATA);
8  auto& lengths = Input(LENGTHS);
9  auto* output = Output(0);
10 
11  CAFFE_ENFORCE_EQ(lengths.dim(), 1, "LENGTHS must be 1-D");
12  CAFFE_ENFORCE_GE(data.dim(), 1, "DATA should be at least 1-D");
13  CAFFE_ENFORCE_EQ(lengths.numel(), data.size(0));
14 
15  // Context::CopyFrom and math::Sum need the same context to avoid race
16  // conditions
17  // why? CPUContext is not used in Sum
18  lengths_host_.CopyFrom(lengths); // sync copy
19  auto lengths_size = lengths_host_.numel();
20  auto* lengths_data = lengths_host_.data<int32_t>();
21 
22  int32_t total_length = 0;
23  CPUContext cpuContext;
24  math::Sum<int32_t, CPUContext>(
25  lengths_size, lengths_data, &total_length, &cpuContext);
26 
27  auto shape = data.sizes().vec();
28  shape[0] = total_length;
29  output->Resize(shape);
30 
31  auto block_bytesize = data.size_from_dim(1) * data.dtype().itemsize();
32  auto src = static_cast<const char*>(data.raw_data());
33  auto out = static_cast<char*>(output->raw_mutable_data(data.dtype()));
34 
35  for (int64_t i = 0; i < lengths_size; ++i) {
36  auto length = lengths_data[i];
37  CAFFE_ENFORCE_GE(length, 0);
38  for (int32_t j = 0; j < length; ++j) {
39  context_.CopyBytesSameDevice(block_bytesize, src, out);
40  out += block_bytesize;
41  }
42  src += block_bytesize;
43  }
44  return true;
45 }
46 
47 REGISTER_CPU_OPERATOR(LengthsTile, LengthsTileOp<CPUContext>);
48 
49 OPERATOR_SCHEMA(LengthsTile)
50  .NumInputs(2)
51  .NumOutputs(1)
52  .SetDoc(R"DOC(
53 Given DATA tensor of rank r >= 1, and LENGTHS tensor of rank 1, duplicate each
54 entry of the outer-most dimension of DATA according to LENGTHS, and concatenate
55 them in an output tensor of rank r.
56 
57 Example:
58  DATA = [
59  [1.0, 1.2],
60  [2.3, 3.4],
61  [4.5, 5.7],
62  [6.8, 7.9],
63  ]
64  LENGTHS = [0, 1, 3, 2]
65  OUTPUT = [
66  [2.3, 3.4],
67  [4.5, 5.7],
68  [4.5, 5.7],
69  [4.5, 5.7],
70  [6.8, 7.9],
71  [6.8, 7.9],
72  ]
73 )DOC")
74  .Input(
75  0,
76  "DATA",
77  "Tensor of rank r >= 1. First dimension must be equal to the size of "
78  "lengths")
79  .Input(1, "LENGTHS", "Tensor of int32 lengths of rank 1")
80  .Output(0, "OUTPUT", "Tensor of rank r");
81 
82 class GetLengthsTileGradient : public GradientMakerBase {
83  using GradientMakerBase::GradientMakerBase;
84  vector<OperatorDef> GetGradientDefs() override {
85  CAFFE_ENFORCE_EQ(def_.input_size(), 2);
86  return SingleGradientDef(
87  "LengthsSum",
88  "",
89  // input 1 is the lengths used to repeat
90  // DATA in the forward pass
91  vector<string>{GO(0), I(1)},
92  // only concerned with the gradient on "DATA"
93  vector<string>{GI(0)});
94  }
95 };
96 REGISTER_GRADIENT(LengthsTile, GetLengthsTileGradient);
97 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13