@@ -160,8 +160,93 @@ void testIm2col() {
160
160
delete context;
161
161
}
162
162
163
+ void testIm2colCPU () {
164
+ paddle::framework::Tensor input;
165
+ paddle::framework::Tensor output;
166
+ int input_height = 3 ;
167
+ int input_width = 4 ;
168
+ int filter_size = 2 ;
169
+ int ic = 2 ;
170
+ std::vector<int > stride ({1 , 1 }); // stride_y, stride_x
171
+ std::vector<int > padding ({0 , 0 });
172
+ std::vector<int > dilation ({1 , 1 }); // dilation_y, dilation_x
173
+ int output_height =
174
+ (input_height - filter_size + padding[0 ] * 2 ) / stride[0 ] + 1 ;
175
+ int output_width =
176
+ (input_width - filter_size + padding[1 ] * 2 ) / stride[1 ] + 1 ;
177
+ float * input_ptr = input.mutable_data <float >({ic, input_height, input_width},
178
+ paddle::platform::CPUPlace ());
179
+ for (int i = 0 ; i < input.numel (); ++i) {
180
+ input_ptr[i] = static_cast <float >(i);
181
+ }
182
+
183
+ paddle::platform::CPUPlace place;
184
+ paddle::platform::CPUDeviceContext context (place);
185
+ output.mutable_data <float >(
186
+ {ic, filter_size, filter_size, output_height, output_width}, place);
187
+ paddle::operators::math::Im2ColFunctor<
188
+ paddle::operators::math::ColFormat::kCFO ,
189
+ paddle::platform::CPUDeviceContext, float >
190
+ im2col;
191
+ im2col (context, input, dilation, stride, padding, &output);
192
+ auto ref_im2col = [&](
193
+ const paddle::framework::Tensor& im, const std::vector<int >& dilation,
194
+ const std::vector<int >& stride, const std::vector<int >& padding,
195
+ paddle::framework::Tensor* col) {
196
+ int im_channels = im.dims ()[0 ];
197
+ int im_height = im.dims ()[1 ];
198
+ int im_width = im.dims ()[2 ];
199
+ int filter_height = col->dims ()[1 ];
200
+ int filter_width = col->dims ()[2 ];
201
+ int output_height = col->dims ()[3 ];
202
+ int output_width = col->dims ()[4 ];
203
+
204
+ int channels_col = im_channels * filter_height * filter_width;
205
+
206
+ const float * im_data = im.data <float >();
207
+ float * col_data = col->data <float >();
208
+ for (int c = 0 ; c < channels_col; ++c) {
209
+ int w_offset = c % filter_width;
210
+ int h_offset = (c / filter_width) % filter_height;
211
+ int c_im = c / (filter_width * filter_height);
212
+ for (int h = 0 ; h < output_height; ++h) {
213
+ int im_row_idx = h * stride[0 ] - padding[0 ] + h_offset * dilation[0 ];
214
+ for (int w = 0 ; w < output_width; ++w) {
215
+ int im_col_idx = w * stride[1 ] - padding[1 ] + w_offset * dilation[1 ];
216
+ int col_idx = (c * output_height + h) * output_width + w;
217
+ int im_idx = (im_row_idx + c_im * im_height) * im_width + im_col_idx;
218
+
219
+ col_data[col_idx] = (im_row_idx < 0 || im_row_idx >= im_height ||
220
+ im_col_idx < 0 || im_col_idx >= im_width)
221
+ ? 0 .f
222
+ : im_data[im_idx];
223
+ }
224
+ }
225
+ }
226
+ };
227
+
228
+ paddle::framework::Tensor ref_output;
229
+ ref_output.mutable_data <float >(
230
+ {ic, filter_size, filter_size, output_height, output_width}, place);
231
+ ref_im2col (input, dilation, stride, padding, &ref_output);
232
+
233
+ float * out_cfo_ptr = output.data <float >();
234
+ for (int i = 0 ; i < ic * filter_size * filter_size; ++i) {
235
+ for (int j = 0 ; j < output_height * output_width; ++j) {
236
+ std::cout << out_cfo_ptr[i * output_height * output_width + j] << " ," ;
237
+ }
238
+ std::cout << std::endl;
239
+ }
240
+
241
+ float * out_ref_ptr = ref_output.data <float >();
242
+ for (int i = 0 ; i < output.numel (); ++i) {
243
+ EXPECT_EQ (out_cfo_ptr[i], out_ref_ptr[i]);
244
+ }
245
+ }
246
+
163
247
TEST (math, im2col) {
164
248
testIm2col<paddle::platform::CPUDeviceContext, paddle::platform::CPUPlace>();
249
+ testIm2colCPU ();
165
250
#ifdef PADDLE_WITH_CUDA
166
251
testIm2col<paddle::platform::CUDADeviceContext,
167
252
paddle::platform::CUDAPlace>();
0 commit comments