Skip to content

Commit d02bb2c

Browse files
committed
Merge pull request BVLC#1922 from erictzeng/lrn_large_region_fix
Cross-channel LRN bounds checking for GPU implementation
2 parents 6cae6f5 + e27c369 commit d02bb2c

File tree

2 files changed

+54
-23
lines changed

2 files changed

+54
-23
lines changed

src/caffe/layers/lrn_layer.cu

+16-23
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,24 @@ __global__ void LRNFillScale(const int nthreads, const Dtype* in,
2626
Dtype accum_scale = 0;
2727
// fill the scale at [n, :, h, w]
2828
// accumulate values
29-
while (head < post_pad) {
29+
while (head < post_pad && head < channels) {
3030
accum_scale += in[head * step] * in[head * step];
3131
++head;
3232
}
33-
// until we reach size, nothing needs to be subtracted
34-
while (head < size) {
35-
accum_scale += in[head * step] * in[head * step];
36-
scale[(head - post_pad) * step] = k + accum_scale * alpha_over_size;
37-
++head;
38-
}
3933
// both add and subtract
4034
while (head < channels) {
4135
accum_scale += in[head * step] * in[head * step];
42-
accum_scale -= in[(head - size) * step] * in[(head - size) * step];
36+
if (head - size >= 0) {
37+
accum_scale -= in[(head - size) * step] * in[(head - size) * step];
38+
}
4339
scale[(head - post_pad) * step] = k + accum_scale * alpha_over_size;
4440
++head;
4541
}
4642
// subtract only
4743
while (head < channels + post_pad) {
48-
accum_scale -= in[(head - size) * step] * in[(head - size) * step];
44+
if (head - size >= 0) {
45+
accum_scale -= in[(head - size) * step] * in[(head - size) * step];
46+
}
4947
scale[(head - post_pad) * step] = k + accum_scale * alpha_over_size;
5048
++head;
5149
}
@@ -143,35 +141,30 @@ __global__ void LRNComputeDiff(const int nthreads, const Dtype* bottom_data,
143141
int post_pad = size - pre_pad - 1;
144142
Dtype accum_ratio = 0;
145143
// accumulate values
146-
while (head < post_pad) {
144+
while (head < post_pad && head < channels) {
147145
accum_ratio += top_diff[head * step] * top_data[head * step] /
148146
scale[head * step];
149147
++head;
150148
}
151-
// until we reach size, nothing needs to be subtracted
152-
while (head < size) {
153-
accum_ratio += top_diff[head * step] * top_data[head * step] /
154-
scale[head * step];
155-
bottom_diff[(head - post_pad) * step] = top_diff[(head - post_pad) * step]
156-
* pow(scale[(head - post_pad) * step], negative_beta) - cache_ratio *
157-
bottom_data[(head - post_pad) * step] * accum_ratio;
158-
++head;
159-
}
160149
// both add and subtract
161150
while (head < channels) {
162151
accum_ratio += top_diff[head * step] * top_data[head * step] /
163152
scale[head * step];
164-
accum_ratio -= top_diff[(head - size) * step] *
165-
top_data[(head - size) * step] / scale[(head - size) * step];
153+
if (head - size >= 0) {
154+
accum_ratio -= top_diff[(head - size) * step] *
155+
top_data[(head - size) * step] / scale[(head - size) * step];
156+
}
166157
bottom_diff[(head - post_pad) * step] = top_diff[(head - post_pad) * step]
167158
* pow(scale[(head - post_pad) * step], negative_beta) - cache_ratio *
168159
bottom_data[(head - post_pad) * step] * accum_ratio;
169160
++head;
170161
}
171162
// subtract only
172163
while (head < channels + post_pad) {
173-
accum_ratio -= top_diff[(head - size) * step] *
174-
top_data[(head - size) * step] / scale[(head - size) * step];
164+
if (head - size >= 0) {
165+
accum_ratio -= top_diff[(head - size) * step] *
166+
top_data[(head - size) * step] / scale[(head - size) * step];
167+
}
175168
bottom_diff[(head - post_pad) * step] = top_diff[(head - post_pad) * step]
176169
* pow(scale[(head - post_pad) * step], negative_beta) - cache_ratio *
177170
bottom_data[(head - post_pad) * step] * accum_ratio;

src/caffe/test/test_lrn_layer.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,22 @@ TYPED_TEST(LRNLayerTest, TestForwardAcrossChannels) {
138138
}
139139
}
140140

141+
TYPED_TEST(LRNLayerTest, TestForwardAcrossChannelsLargeRegion) {
142+
typedef typename TypeParam::Dtype Dtype;
143+
LayerParameter layer_param;
144+
layer_param.mutable_lrn_param()->set_local_size(15);
145+
LRNLayer<Dtype> layer(layer_param);
146+
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
147+
layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_);
148+
Blob<Dtype> top_reference;
149+
this->ReferenceLRNForward(*(this->blob_bottom_), layer_param,
150+
&top_reference);
151+
for (int i = 0; i < this->blob_bottom_->count(); ++i) {
152+
EXPECT_NEAR(this->blob_top_->cpu_data()[i], top_reference.cpu_data()[i],
153+
this->epsilon_);
154+
}
155+
}
156+
141157
TYPED_TEST(LRNLayerTest, TestGradientAcrossChannels) {
142158
typedef typename TypeParam::Dtype Dtype;
143159
LayerParameter layer_param;
@@ -159,6 +175,28 @@ TYPED_TEST(LRNLayerTest, TestGradientAcrossChannels) {
159175
this->blob_top_vec_);
160176
}
161177

178+
TYPED_TEST(LRNLayerTest, TestGradientAcrossChannelsLargeRegion) {
179+
typedef typename TypeParam::Dtype Dtype;
180+
LayerParameter layer_param;
181+
layer_param.mutable_lrn_param()->set_local_size(15);
182+
LRNLayer<Dtype> layer(layer_param);
183+
GradientChecker<Dtype> checker(1e-2, 1e-2);
184+
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
185+
layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_);
186+
for (int i = 0; i < this->blob_top_->count(); ++i) {
187+
this->blob_top_->mutable_cpu_diff()[i] = 1.;
188+
}
189+
vector<bool> propagate_down(this->blob_bottom_vec_.size(), true);
190+
layer.Backward(this->blob_top_vec_, propagate_down,
191+
this->blob_bottom_vec_);
192+
// for (int i = 0; i < this->blob_bottom_->count(); ++i) {
193+
// std::cout << "CPU diff " << this->blob_bottom_->cpu_diff()[i]
194+
// << std::endl;
195+
// }
196+
checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_,
197+
this->blob_top_vec_);
198+
}
199+
162200
TYPED_TEST(LRNLayerTest, TestSetupWithinChannel) {
163201
typedef typename TypeParam::Dtype Dtype;
164202
LayerParameter layer_param;

0 commit comments

Comments
 (0)