@@ -86,6 +86,70 @@ TYPED_TEST(ScalarLayerTest, TestForwardEltwise) {
8686 }
8787}
8888
89+ TYPED_TEST (ScalarLayerTest, TestForwardEltwiseInPlace) {
90+ typedef typename TypeParam::Dtype Dtype;
91+ this ->blob_top_vec_ [0 ] = this ->blob_bottom_ ; // in-place computation
92+ Blob<Dtype> orig_bottom (this ->blob_bottom_ ->shape ());
93+ orig_bottom.CopyFrom (*this ->blob_bottom_ );
94+ this ->blob_bottom_vec_ .push_back (this ->blob_bottom_eltwise_ );
95+ LayerParameter layer_param;
96+ shared_ptr<ScalarLayer<Dtype> > layer (new ScalarLayer<Dtype>(layer_param));
97+ layer->SetUp (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
98+ layer->Forward (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
99+ const Dtype* data = this ->blob_bottom_ ->cpu_data ();
100+ const int count = this ->blob_bottom_ ->count ();
101+ const Dtype* in_data_a = orig_bottom.cpu_data ();
102+ const Dtype* in_data_b = this ->blob_bottom_eltwise_ ->cpu_data ();
103+ for (int i = 0 ; i < count; ++i) {
104+ EXPECT_NEAR (data[i], in_data_a[i] * in_data_b[i], 1e-5 );
105+ }
106+ }
107+
108+ TYPED_TEST (ScalarLayerTest, TestBackwardEltwiseInPlace) {
109+ typedef typename TypeParam::Dtype Dtype;
110+ Blob<Dtype> orig_bottom (this ->blob_bottom_ ->shape ());
111+ orig_bottom.CopyFrom (*this ->blob_bottom_ );
112+ this ->blob_bottom_vec_ .push_back (this ->blob_bottom_eltwise_ );
113+ LayerParameter layer_param;
114+ shared_ptr<ScalarLayer<Dtype> > layer (new ScalarLayer<Dtype>(layer_param));
115+ Blob<Dtype> top_diff (this ->blob_bottom_ ->shape ());
116+ FillerParameter filler_param;
117+ filler_param.set_type (" gaussian" );
118+ filler_param.set_std (1 );
119+ GaussianFiller<Dtype> filler (filler_param);
120+ filler.Fill (&top_diff);
121+ vector<bool > propagate_down (2 , true );
122+ // Run forward + backward without in-place computation;
123+ // save resulting bottom diffs.
124+ layer->SetUp (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
125+ layer->Forward (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
126+ caffe_copy (top_diff.count (), top_diff.cpu_data (),
127+ this ->blob_top_ ->mutable_cpu_diff ());
128+ layer->Backward (this ->blob_top_vec_ , propagate_down, this ->blob_bottom_vec_ );
129+ const bool kReshape = true ;
130+ const bool kCopyDiff = true ;
131+ Blob<Dtype> orig_bottom_diff;
132+ orig_bottom_diff.CopyFrom (*this ->blob_bottom_ , kCopyDiff , kReshape );
133+ Blob<Dtype> orig_scalar_diff;
134+ orig_scalar_diff.CopyFrom (*this ->blob_bottom_eltwise_ ,
135+ kCopyDiff , kReshape );
136+ // Rerun forward + backward with in-place computation;
137+ // check that resulting bottom diffs are the same.
138+ this ->blob_top_vec_ [0 ] = this ->blob_bottom_ ; // in-place computation
139+ layer->Forward (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
140+ caffe_copy (top_diff.count (), top_diff.cpu_data (),
141+ this ->blob_bottom_ ->mutable_cpu_diff ());
142+ layer->Backward (this ->blob_top_vec_ , propagate_down, this ->blob_bottom_vec_ );
143+ for (int i = 0 ; i < this ->blob_bottom_ ->count (); ++i) {
144+ EXPECT_NEAR (orig_bottom_diff.cpu_diff ()[i],
145+ this ->blob_bottom_ ->cpu_diff ()[i], 1e-5 );
146+ }
147+ for (int i = 0 ; i < this ->blob_bottom_eltwise_ ->count (); ++i) {
148+ EXPECT_NEAR (orig_scalar_diff.cpu_diff ()[i],
149+ this ->blob_bottom_eltwise_ ->cpu_diff ()[i], 1e-5 );
150+ }
151+ }
152+
89153TYPED_TEST (ScalarLayerTest, TestForwardEltwiseWithParam) {
90154 typedef typename TypeParam::Dtype Dtype;
91155 LayerParameter layer_param;
@@ -151,6 +215,77 @@ TYPED_TEST(ScalarLayerTest, TestForwardBroadcastMiddle) {
151215 }
152216}
153217
218+ TYPED_TEST (ScalarLayerTest, TestForwardBroadcastMiddleInPlace) {
219+ typedef typename TypeParam::Dtype Dtype;
220+ this ->blob_top_vec_ [0 ] = this ->blob_bottom_ ; // in-place computation
221+ Blob<Dtype> orig_bottom (this ->blob_bottom_ ->shape ());
222+ orig_bottom.CopyFrom (*this ->blob_bottom_ );
223+ this ->blob_bottom_vec_ .push_back (this ->blob_bottom_broadcast_1_ );
224+ LayerParameter layer_param;
225+ layer_param.mutable_scalar_param ()->set_axis (1 );
226+ shared_ptr<ScalarLayer<Dtype> > layer (new ScalarLayer<Dtype>(layer_param));
227+ layer->SetUp (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
228+ layer->Forward (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
229+ for (int n = 0 ; n < this ->blob_bottom_ ->num (); ++n) {
230+ for (int c = 0 ; c < this ->blob_bottom_ ->channels (); ++c) {
231+ for (int h = 0 ; h < this ->blob_bottom_ ->height (); ++h) {
232+ for (int w = 0 ; w < this ->blob_bottom_ ->width (); ++w) {
233+ EXPECT_NEAR (this ->blob_bottom_ ->data_at (n, c, h, w),
234+ orig_bottom.data_at (n, c, h, w) *
235+ this ->blob_bottom_broadcast_1_ ->data_at (c, h, 0 , 0 ),
236+ 1e-5 );
237+ }
238+ }
239+ }
240+ }
241+ }
242+
243+ TYPED_TEST (ScalarLayerTest, TestBackwardBroadcastMiddleInPlace) {
244+ typedef typename TypeParam::Dtype Dtype;
245+ Blob<Dtype> orig_bottom (this ->blob_bottom_ ->shape ());
246+ orig_bottom.CopyFrom (*this ->blob_bottom_ );
247+ this ->blob_bottom_vec_ .push_back (this ->blob_bottom_broadcast_1_ );
248+ LayerParameter layer_param;
249+ layer_param.mutable_scalar_param ()->set_axis (1 );
250+ shared_ptr<ScalarLayer<Dtype> > layer (new ScalarLayer<Dtype>(layer_param));
251+ Blob<Dtype> top_diff (this ->blob_bottom_ ->shape ());
252+ FillerParameter filler_param;
253+ filler_param.set_type (" gaussian" );
254+ filler_param.set_std (1 );
255+ GaussianFiller<Dtype> filler (filler_param);
256+ filler.Fill (&top_diff);
257+ vector<bool > propagate_down (2 , true );
258+ // Run forward + backward without in-place computation;
259+ // save resulting bottom diffs.
260+ layer->SetUp (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
261+ layer->Forward (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
262+ caffe_copy (top_diff.count (), top_diff.cpu_data (),
263+ this ->blob_top_ ->mutable_cpu_diff ());
264+ layer->Backward (this ->blob_top_vec_ , propagate_down, this ->blob_bottom_vec_ );
265+ const bool kReshape = true ;
266+ const bool kCopyDiff = true ;
267+ Blob<Dtype> orig_bottom_diff;
268+ orig_bottom_diff.CopyFrom (*this ->blob_bottom_ , kCopyDiff , kReshape );
269+ Blob<Dtype> orig_scalar_diff;
270+ orig_scalar_diff.CopyFrom (*this ->blob_bottom_broadcast_1_ ,
271+ kCopyDiff , kReshape );
272+ // Rerun forward + backward with in-place computation;
273+ // check that resulting bottom diffs are the same.
274+ this ->blob_top_vec_ [0 ] = this ->blob_bottom_ ; // in-place computation
275+ layer->Forward (this ->blob_bottom_vec_ , this ->blob_top_vec_ );
276+ caffe_copy (top_diff.count (), top_diff.cpu_data (),
277+ this ->blob_bottom_ ->mutable_cpu_diff ());
278+ layer->Backward (this ->blob_top_vec_ , propagate_down, this ->blob_bottom_vec_ );
279+ for (int i = 0 ; i < this ->blob_bottom_ ->count (); ++i) {
280+ EXPECT_NEAR (orig_bottom_diff.cpu_diff ()[i],
281+ this ->blob_bottom_ ->cpu_diff ()[i], 1e-5 );
282+ }
283+ for (int i = 0 ; i < this ->blob_bottom_broadcast_1_ ->count (); ++i) {
284+ EXPECT_NEAR (orig_scalar_diff.cpu_diff ()[i],
285+ this ->blob_bottom_broadcast_1_ ->cpu_diff ()[i], 1e-5 );
286+ }
287+ }
288+
154289TYPED_TEST (ScalarLayerTest, TestForwardBroadcastMiddleWithParam) {
155290 typedef typename TypeParam::Dtype Dtype;
156291 LayerParameter layer_param;
0 commit comments