1 #include "caffe2/operators/pack_segments.h" 7 bool PackSegmentsOp<CPUContext>::DoRunWithType() {
9 TensorTypes2<char, int32_t, int64_t, float, std::string>,
10 T>::call(
this, Input(DATA));
14 template <
typename T,
typename Data_T>
15 bool PackSegmentsOp<CPUContext>::DoRunWithType2() {
16 const auto& data = Input(DATA);
17 const auto& lengths = Input(LENGTHS);
19 Tensor* presence_mask =
nullptr;
20 if (return_presence_mask_) {
21 presence_mask = Output(1);
24 CAFFE_ENFORCE_GE(data.dim(), 1,
"DATA should be at least 1-D");
25 CAFFE_ENFORCE_EQ(lengths.dim(), 1,
"LENGTH should be 1-D");
28 const T* l = lengths.template data<T>();
30 int64_t total_length = 0;
31 for (
T i = 0; i < lengths.size(0); ++i) {
32 max_length = std::max(max_length, l[i]);
35 if (max_length_ != -1) {
40 "Pre-defined max_length should be greater than the real max_length");
41 max_length = max_length_;
48 " PackSegments requires that the sum of the lengths ",
50 " is equal to the first data dimension ",
55 shape[0] = max_length;
56 shape.insert(shape.begin(), lengths.numel());
57 auto* output = Output(0, shape, at::dtype(data.dtype()));
60 auto* out =
static_cast<char*
>(output->raw_mutable_data(data.dtype()));
62 bool* presence_mask_data =
nullptr;
63 if (return_presence_mask_) {
65 std::vector<int64_t> presence_shape{lengths.numel(), max_length};
66 presence_mask->Resize(presence_shape);
67 presence_mask_data = presence_mask->template mutable_data<bool>();
76 if (output->template IsType<float>()) {
77 math::Set<float, CPUContext>(
80 output->template mutable_data<float>(),
83 if (return_presence_mask_) {
84 memset(presence_mask_data, (
int)
false, presence_mask->numel());
87 auto block_size = data.size_from_dim(1);
88 auto block_bytesize = data.itemsize() * block_size;
89 const auto* d =
static_cast<const char*
>(data.raw_data());
91 for (int64_t i = 0; i < lengths.size(0); ++i) {
92 context_.CopyItemsSameDevice(
95 d + block_bytesize * start,
96 out + block_bytesize * max_length * i);
97 if (return_presence_mask_) {
98 memset(presence_mask_data + max_length * i, (
int)
true, l[i]);
107 template <
typename T>
108 bool UnpackSegmentsOp<CPUContext>::DoRunWithType() {
109 return DispatchHelper<
110 TensorTypes2<char, int32_t, int64_t, float, std::string>,
111 T>::call(
this, Input(DATA));
115 template <
typename T,
typename Data_T>
116 bool UnpackSegmentsOp<CPUContext>::DoRunWithType2() {
117 const auto& data = Input(DATA);
118 const auto& lengths = Input(LENGTHS);
119 auto* output = Output(0);
121 CAFFE_ENFORCE_GE(data.dim(), 2,
"DATA should be at least 2-D");
122 CAFFE_ENFORCE_EQ(lengths.dim(), 1,
"LENGTH should be 1-D");
123 if (max_length_ != -1) {
127 "max_length should be equal to the second dimension of the packed segments");
129 const T* l = lengths.template data<T>();
131 int64_t total_l = std::accumulate(l, l + lengths.size(0), (int64_t)0);
133 auto shape = data.sizes().vec();
135 shape[0], lengths.size(0),
"LENGTH should match DATA in dimension 0");
136 shape.erase(shape.begin());
138 output->Resize(shape);
140 auto* out =
static_cast<char*
>(output->raw_mutable_data(data.dtype()));
141 if (!(data.size(0) && data.size(1))) {
144 auto block_size = data.size_from_dim(2);
145 auto block_bytesize = data.itemsize() * block_size;
146 const auto* d =
static_cast<const char*
>(data.raw_data());
148 for (int64_t i = 0; i < lengths.size(0); ++i) {
149 context_.CopyItemsSameDevice(
152 d + block_bytesize * data.size(1) * i,
153 out + block_bytesize * start);
159 REGISTER_CPU_OPERATOR(PackSegments, PackSegmentsOp<CPUContext>);
160 REGISTER_CPU_OPERATOR(UnpackSegments, UnpackSegmentsOp<CPUContext>);
162 OPERATOR_SCHEMA(PackSegments)
166 "Map N dim tensor to N+1 dim based on length blob. Sequences that \ 167 are shorter than the longest sequence are padded with zeros.")
171 "1-d int/long tensor contains the length in each of the output.")
172 .Input(1,
"tensor",
"N dim Tensor.")
177 "where dim(1) is the max length" 178 ", dim(0) is the batch size.")
182 "2 dim boolean tensor" 183 ", false where packed_tensor is padded, true otherwise.")
184 .Arg(
"max_length",
"The pre-defined max_length for the packed segments")
187 "Padding number in the packed segments. Use true to pad \ 188 -infinity, otherwise pad zeros")
190 "return_presence_mask",
191 "bool whether to return presence mask, false by default");
192 OPERATOR_SCHEMA(UnpackSegments)
195 .SetDoc(
"Map N+1 dim tensor to N dim based on length blob")
199 "1-d int/long tensor contains the length in each of the input.")
200 .Input(1,
"tensor",
"N+1 dim Tensor.")
201 .Output(0,
"packed_tensor",
"N dim Tensor")
202 .Arg(
"max_length",
"The pre-defined max_length for the packed segments");
205 using GradientMakerBase::GradientMakerBase;
206 vector<OperatorDef> GetGradientDefs()
override {
210 vector<string>{I(0), GO(0)},
211 vector<string>{GI(1)});
217 using GradientMakerBase::GradientMakerBase;
218 vector<OperatorDef> GetGradientDefs()
override {
220 "PackSegments",
"", vector<string>{I(0), GO(0)}, vector<string>{GI(1)});
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
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 ...