@@ -18,128 +18,122 @@ namespace paddle {
18
18
namespace operators {
19
19
namespace math {
20
20
21
+ template <typename T>
22
+ void CopyValidData (framework::Tensor* dst_tensor,
23
+ const framework::Tensor* src_tensor,
24
+ const framework::Vector<size_t >& seq_offsets,
25
+ int pad_seq_len, int step_width, bool norm_by_len,
26
+ CopyType type, PadLayout layout) {
27
+ int seq_num = seq_offsets.size () - 1 ;
28
+ const T* src_data = src_tensor->data <T>();
29
+ T* dst_data = dst_tensor->data <T>();
30
+
31
+ int seq_cpy_gap = step_width;
32
+ int pad_cpy_gap =
33
+ layout == kBatchLengthWidth ? step_width : seq_num * step_width;
34
+ for (int seq_idx = 0 ; seq_idx < seq_num; ++seq_idx) {
35
+ int valid_seq_len = seq_offsets[seq_idx + 1 ] - seq_offsets[seq_idx];
36
+ PADDLE_ENFORCE_GE (
37
+ pad_seq_len, valid_seq_len,
38
+ " The padded sequence length can not be less than its original length." );
39
+ int seq_data_offset = seq_offsets[seq_idx] * step_width;
40
+ int pad_data_offset = layout == kBatchLengthWidth
41
+ ? seq_idx * pad_seq_len * step_width
42
+ : seq_idx * step_width;
43
+ float scale = 1 .0f / static_cast <float >(valid_seq_len);
44
+
45
+ for (int step_idx = 0 ; step_idx < valid_seq_len; ++step_idx) {
46
+ const T* src =
47
+ src_data + (type == kSeqToPad ? seq_data_offset : pad_data_offset);
48
+ T* dst =
49
+ dst_data + (type == kSeqToPad ? pad_data_offset : seq_data_offset);
50
+ memcpy (dst, src, step_width * sizeof (T));
51
+ if (norm_by_len) {
52
+ for (int i = 0 ; i < step_width; ++i) {
53
+ *(dst + i) *= scale;
54
+ }
55
+ }
56
+ seq_data_offset += seq_cpy_gap;
57
+ pad_data_offset += pad_cpy_gap;
58
+ }
59
+ }
60
+ }
61
+
21
62
template <typename T>
22
63
class PaddingLoDTensorFunctor <platform::CPUDeviceContext, T> {
23
64
public:
24
65
void operator ()(const platform::CPUDeviceContext& context,
25
- const framework::LoDTensor& seq, framework::Tensor* padding,
26
- bool norm_by_times) {
27
- auto lod = seq.lod ();
28
- PADDLE_ENFORCE_GT (lod.size (), 0UL ,
29
- " The LoD of LoDTensor seq should not be null." );
30
-
31
- const size_t level = 0 ;
32
- framework::LoD abs_offset_lod = framework::ToAbsOffset (lod);
33
-
34
- auto seq_dims = seq.dims ();
35
- PADDLE_ENFORCE_EQ (seq_dims[0 ],
36
- static_cast <int64_t >(abs_offset_lod[level].back ()),
37
- " The first dimension of LoDTensor seq should be "
38
- " equal to the sum of all sequences's length." );
39
-
40
- auto padding_dims = padding->dims ();
41
- PADDLE_ENFORCE_EQ (padding_dims.size (), 3UL ,
42
- " The input padding should be a 3-D Tensor of shape "
43
- " [max_sequence_length, num_sequences, sequence_width]." );
44
-
45
- const int64_t max_sequence_length = MaximumSequenceLength (lod, level);
46
- PADDLE_ENFORCE_EQ (padding_dims[0 ], max_sequence_length,
47
- " The first dimension of Tensor padding should be the "
48
- " maximum length of all sequences in LoDTensor seq." );
49
-
50
- const int64_t num_sequences = abs_offset_lod[level].size () - 1 ;
51
- PADDLE_ENFORCE_EQ (padding_dims[1 ], num_sequences,
52
- " The second dimension of Tensor padding should be the "
53
- " number of sequences in LoDTensor seq." );
54
-
55
- const int64_t sequence_width = seq.numel () / seq_dims[0 ];
56
- PADDLE_ENFORCE_EQ (padding_dims[2 ], sequence_width,
57
- " The third dimension of Tensor padding should be the "
58
- " width of sequence in LoDTensor seq." );
59
-
60
- const T* seq_data = seq.data <T>();
61
- T* padding_data = padding->data <T>();
62
- for (int64_t i = 0 ; i < max_sequence_length; ++i) {
63
- for (int64_t j = 0 ; j < num_sequences; ++j) {
64
- int64_t start_pos = abs_offset_lod[level][j];
65
- int64_t sequence_length = abs_offset_lod[level][j + 1 ] - start_pos;
66
- if (i < sequence_length) {
67
- // i > 0 => sequence_length > 0
68
- T scale =
69
- norm_by_times ? (1 .0f / static_cast <T>(sequence_length)) : 1 .0f ;
70
- for (int64_t k = 0 ; k < sequence_width; ++k) {
71
- padding_data[(i * num_sequences + j) * sequence_width + k] =
72
- seq_data[(start_pos + i) * sequence_width + k] * scale;
73
- }
74
- } else {
75
- memset (padding_data + (i * num_sequences + j) * sequence_width, 0 ,
76
- sequence_width * sizeof (T));
77
- }
66
+ const framework::LoDTensor& seq_tensor,
67
+ framework::LoDTensor* pad_tensor,
68
+ const framework::LoDTensor& pad_value, int pad_seq_len = -1 ,
69
+ int lod_level = 0 , bool norm_by_times = false ,
70
+ const PadLayout layout = kBatchLengthWidth ) {
71
+ auto seq_lod = seq_tensor.lod ();
72
+ const auto seq_offsets = framework::ToAbsOffset (seq_lod)[lod_level];
73
+ const auto & seq_tensor_dims = seq_tensor.dims ();
74
+ const auto & pad_tensor_dims = pad_tensor->dims ();
75
+ if (pad_seq_len == -1 ) {
76
+ pad_seq_len = MaximumSequenceLength (seq_offsets);
77
+ }
78
+ int step_width = seq_tensor.numel () / seq_tensor_dims[0 ];
79
+
80
+ CheckDims (seq_tensor_dims, pad_tensor_dims, seq_offsets, pad_seq_len,
81
+ step_width, layout);
82
+ PADDLE_ENFORCE (pad_value.numel () == 1 || pad_value.numel () == step_width,
83
+ " The numel of 'pad_value' can only be 1 or be equal to the "
84
+ " 'step_width'." );
85
+
86
+ // fill padding value
87
+ T* pad_data = pad_tensor->data <T>();
88
+ const T* pad_value_data = pad_value.data <T>();
89
+ if (pad_value.numel () == 1 ) {
90
+ for (int i = 0 ; i < pad_tensor->numel (); ++i) {
91
+ pad_data[i] = *pad_value_data;
92
+ }
93
+ } else {
94
+ for (int i = 0 ; i < pad_tensor->numel (); i += step_width) {
95
+ memcpy (pad_data + i, pad_value_data, step_width * sizeof (T));
78
96
}
79
97
}
98
+
99
+ CopyValidData<T>(pad_tensor, &seq_tensor, seq_offsets, pad_seq_len,
100
+ step_width, norm_by_times, kSeqToPad , layout);
80
101
}
81
102
};
82
103
83
104
template <typename T>
84
105
class UnpaddingLoDTensorFunctor <platform::CPUDeviceContext, T> {
85
106
public:
86
107
void operator ()(const platform::CPUDeviceContext& context,
87
- framework::LoDTensor* seq, const framework::Tensor& padding,
88
- bool norm_by_times) {
89
- auto lod = seq->lod ();
90
- PADDLE_ENFORCE_GT (lod.size (), 0UL ,
91
- " The LoD of LoDTensor seq should not be null." );
92
-
93
- const size_t level = 0 ;
94
- framework::LoD abs_offset_lod = framework::ToAbsOffset (lod);
95
-
96
- auto seq_dims = seq->dims ();
97
- PADDLE_ENFORCE_EQ (seq_dims[0 ],
98
- static_cast <int64_t >(abs_offset_lod[level].back ()),
99
- " The first dimension of LoDTensor seq should be "
100
- " equal to the sum of all sequences's length." );
101
-
102
- auto padding_dims = padding.dims ();
103
- PADDLE_ENFORCE_EQ (padding_dims.size (), 3UL ,
104
- " The input padding should be a 3-D Tensor of shape "
105
- " [max_sequnece_length, num_sequences, sequence_width]." );
106
-
107
- const int64_t max_sequence_length = MaximumSequenceLength (lod, level);
108
- PADDLE_ENFORCE_EQ (padding_dims[0 ], max_sequence_length,
109
- " The first dimension of Tensor padding should be "
110
- " the maximum length of all sequences in LoDTensor seq." );
111
-
112
- const int64_t num_sequences = abs_offset_lod[level].size () - 1 ;
113
- PADDLE_ENFORCE_EQ (padding_dims[1 ], num_sequences,
114
- " The second dimension of Tensor padding should be "
115
- " the number of sequences in LoDTensor seq." );
116
-
117
- const int64_t sequence_width = seq->numel () / seq_dims[0 ];
118
- PADDLE_ENFORCE_EQ (padding_dims[2 ], sequence_width,
119
- " The third dimension of Tensor padding should be the "
120
- " width of sequence in LoDTensor seq." );
121
-
122
- const T* padding_data = padding.data <T>();
123
- T* seq_data = seq->data <T>();
124
- for (int64_t i = 0 ; i < num_sequences; ++i) {
125
- int64_t start_pos = abs_offset_lod[level][i];
126
- int64_t sequence_length = abs_offset_lod[level][i + 1 ] - start_pos;
127
- for (int64_t j = 0 ; j < sequence_length; ++j) {
128
- // sequence_width > j > 0
129
- T scale =
130
- norm_by_times ? (1 .0f / static_cast <T>(sequence_length)) : 1 .0f ;
131
- for (int64_t k = 0 ; k < sequence_width; ++k) {
132
- seq_data[(start_pos + j) * sequence_width + k] =
133
- padding_data[(j * num_sequences + i) * sequence_width + k] *
134
- scale;
135
- }
136
- }
108
+ const framework::LoDTensor& pad_tensor,
109
+ framework::LoDTensor* seq_tensor, int pad_seq_len = -1 ,
110
+ int lod_level = 0 , bool norm_by_times = false ,
111
+ const PadLayout layout = kBatchLengthWidth ) {
112
+ auto seq_offsets = framework::ToAbsOffset (seq_tensor->lod ())[lod_level];
113
+ const auto & seq_tensor_dims = seq_tensor->dims ();
114
+ const auto & pad_tensor_dims = pad_tensor.dims ();
115
+ if (pad_seq_len == -1 ) {
116
+ pad_seq_len = MaximumSequenceLength (seq_offsets);
137
117
}
118
+ int step_width = seq_tensor->numel () / seq_tensor_dims[0 ];
119
+
120
+ CheckDims (seq_tensor_dims, pad_tensor_dims, seq_offsets, pad_seq_len,
121
+ step_width, layout);
122
+
123
+ CopyValidData<T>(seq_tensor, &pad_tensor, seq_offsets, pad_seq_len,
124
+ step_width, norm_by_times, kPadToSeq , layout);
138
125
}
139
126
};
140
127
128
+ template class PaddingLoDTensorFunctor <platform::CPUDeviceContext, int >;
129
+ template class PaddingLoDTensorFunctor <platform::CPUDeviceContext, int64_t >;
141
130
template class PaddingLoDTensorFunctor <platform::CPUDeviceContext, float >;
131
+ template class PaddingLoDTensorFunctor <platform::CPUDeviceContext, double >;
132
+
133
+ template class UnpaddingLoDTensorFunctor <platform::CPUDeviceContext, int >;
134
+ template class UnpaddingLoDTensorFunctor <platform::CPUDeviceContext, int64_t >;
142
135
template class UnpaddingLoDTensorFunctor <platform::CPUDeviceContext, float >;
136
+ template class UnpaddingLoDTensorFunctor <platform::CPUDeviceContext, double >;
143
137
144
138
} // namespace math
145
139
} // namespace operators
0 commit comments