| 11 | |
| 12 | template <typename T, typename Pooler> |
| 13 | void forward_impl( |
| 14 | _megdnn_tensor_in src, _megdnn_tensor_in rois, _megdnn_tensor_in dst, |
| 15 | _megdnn_tensor_out index, float spatial_scale) { |
| 16 | auto C = src.layout.shape[1], IH = src.layout.shape[2], IW = src.layout.shape[3]; |
| 17 | auto OH = dst.layout.shape[2], OW = dst.layout.shape[3]; |
| 18 | |
| 19 | auto total_nr_elem = dst.layout.total_nr_elems(); |
| 20 | auto pooled_height = OH, pooled_width = OW; |
| 21 | auto height = IH, width = IW; |
| 22 | auto channels = C; |
| 23 | for (size_t i = 0; i < total_nr_elem; ++i) { |
| 24 | int pw = i % pooled_width; |
| 25 | int ph = (i / pooled_width) % pooled_height; |
| 26 | int c = (i / pooled_width / pooled_height) % channels; |
| 27 | int n = i / pooled_width / pooled_height / channels; |
| 28 | auto rois_ptr = rois.ptr<T>() + n * 5; |
| 29 | int roi_batch_ind = rois_ptr[0]; |
| 30 | int roi_start_w = round(rois_ptr[1] * spatial_scale); |
| 31 | int roi_start_h = round(rois_ptr[2] * spatial_scale); |
| 32 | int roi_end_w = round(rois_ptr[3] * spatial_scale); |
| 33 | int roi_end_h = round(rois_ptr[4] * spatial_scale); |
| 34 | // Force malformed ROIs to be 1x1 |
| 35 | int roi_width = std::max(roi_end_w - roi_start_w + 1, 1); |
| 36 | int roi_height = std::max(roi_end_h - roi_start_h + 1, 1); |
| 37 | float bin_size_h = |
| 38 | static_cast<float>(roi_height) / static_cast<float>(pooled_height); |
| 39 | float bin_size_w = |
| 40 | static_cast<float>(roi_width) / static_cast<float>(pooled_width); |
| 41 | |
| 42 | int hstart = static_cast<int>(floor(static_cast<float>(ph) * bin_size_h)); |
| 43 | int wstart = static_cast<int>(floor(static_cast<float>(pw) * bin_size_w)); |
| 44 | int hend = static_cast<int>(ceil(static_cast<float>(ph + 1) * bin_size_h)); |
| 45 | int wend = static_cast<int>(ceil(static_cast<float>(pw + 1) * bin_size_w)); |
| 46 | // Add roi offsets and clip to input boundaries |
| 47 | hstart = std::min<int>(std::max(hstart + roi_start_h, 0), height); |
| 48 | hend = std::min<int>(std::max(hend + roi_start_h, 0), height); |
| 49 | wstart = std::min<int>(std::max(wstart + roi_start_w, 0), width); |
| 50 | wend = std::min<int>(std::max(wend + roi_start_w, 0), width); |
| 51 | |
| 52 | Pooler pooler; |
| 53 | auto feat_map_ptr = |
| 54 | src.ptr<T>() + (roi_batch_ind * channels + c) * height * width; |
| 55 | for (int h = hstart; h < hend; ++h) { |
| 56 | for (int w = wstart; w < wend; ++w) { |
| 57 | int bottom_i = h * width + w; |
| 58 | pooler.feed(feat_map_ptr[bottom_i], bottom_i); |
| 59 | } |
| 60 | } |
| 61 | pooler.writeback_val(dst.ptr<T>()[i]); |
| 62 | pooler.writeback_idx(index.ptr<dt_int32>()[i]); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | template <typename T> |
| 67 | void forward( |
nothing calls this directly
no test coverage detected