| 38 | namespace LRNImpl { |
| 39 | |
| 40 | void lrn_kernel(int i, int id, void* data, const float* input, float* output, float* square, |
| 41 | int h, int w, int channel, int local_size, float alpha_over_size, float beta) |
| 42 | { |
| 43 | int step = ((int*)data)[0]; |
| 44 | int channel_size = h * w; |
| 45 | float* accum_square = ( float* )(std::malloc(channel_size * sizeof(float))); |
| 46 | |
| 47 | int start_c = step * id; |
| 48 | int end_c = step * id + step; |
| 49 | for(int c = start_c; c < end_c; c++) |
| 50 | { |
| 51 | int c_start = c - local_size / 2; |
| 52 | int c_end = c + local_size / 2; |
| 53 | |
| 54 | std::memset(accum_square, 0x0, channel_size * sizeof(float)); |
| 55 | |
| 56 | for(int l = c_start; l <= c_end; l++) |
| 57 | { |
| 58 | if(l < 0 || l >= channel) |
| 59 | continue; |
| 60 | |
| 61 | for(int n = 0; n < channel_size; n++) |
| 62 | { |
| 63 | accum_square[n] += square[l * channel_size + n]; |
| 64 | } |
| 65 | } |
| 66 | /* get the output */ |
| 67 | const float* cur_input = input + c * channel_size; |
| 68 | float* cur_output = output + c * channel_size; |
| 69 | for(int n = 0; n < channel_size; n++) |
| 70 | { |
| 71 | *cur_output++ = *cur_input++ * std::pow(1.0f + alpha_over_size * accum_square[n], -beta); |
| 72 | } |
| 73 | |
| 74 | } |
| 75 | |
| 76 | std::free(accum_square); |
| 77 | } |
| 78 | struct LRNOps : public NodeOps |
| 79 | { |
| 80 | LRNOps() |