code: def forward_gpu(self, inputs):
      self.retain_inputs((1, 2))
      self._bottom_data_shape = inputs[0].shape
  
      bottom_data, bottom_rois, bottom_roi_indices = inputs
      channel, height, width = bottom_data.shape[1:]
      if self.out_c is None:
          if channel % (self.group_size * self.group_size) != 0:
              raise ValueError(
                  "input channel must be divided by group_size * group_size:"
                  "{} % {} != 0".format(
                      channel, self.group_size * self.group_size
                  )
              )
          out_c = channel // (self.group_size * self.group_size)
      else:
          if channel != self.out_c * self.group_size * self.group_size:
              raise ValueError(
                  "input channel must be equal to "
                  "outsize[0] * group_size * group_size: {} != {}".format(
                      channel,
                      self.out_c * self.group_size * self.group_size,
                  )
              )
          out_c = self.out_c
      n_roi = bottom_rois.shape[0]
      top_data = cuda.cupy.empty(
          (n_roi, out_c, self.out_h, self.out_w), dtype=np.float32
      )
      cuda.elementwise(
          """
              raw T bottom_data, raw T bottom_rois,
              raw int32 bottom_roi_indices,
              T spatial_scale, int32 channel,
              int32 height, int32 width,
              int32 pooled_dim, int32 pooled_height, int32 pooled_width,
              int32 group_size
              """,
          "T top_data",
          """
              // pos in output filter
              int ph = (i / pooled_width) % pooled_height;
              int pw = i % pooled_width;
              int ctop = (i / pooled_width / pooled_height) % pooled_dim;
              int n = i / pooled_width / pooled_height / pooled_dim;
  
              int roi_batch_ind = bottom_roi_indices[n];
              T roi_start_h = bottom_rois[n * 4 + 0] * spatial_scale;
              T roi_start_w = bottom_rois[n * 4 + 1] * spatial_scale;
              T roi_end_h = bottom_rois[n * 4 + 2] * spatial_scale;
              T roi_end_w = bottom_rois[n * 4 + 3] * spatial_scale;
  
              // Force too small ROIs to be 1x1
              T roi_height = max(roi_end_h - roi_start_h, 0.1);
              T roi_width = max(roi_end_w - roi_start_w, 0.1);  // avoid 0
  
              // Compute w and h at bottom
              T bin_size_h = roi_height / static_cast<T>(pooled_height);
              T bin_size_w = roi_width / static_cast<T>(pooled_width);
  
              int hstart = floor(
                  static_cast<T>(ph) * bin_size_h + roi_start_h);
              int wstart = floor(
                  static_cast<T>(pw) * bin_size_w + roi_start_w);
              int hend = ceil(
                  static_cast<T>(ph + 1) * bin_size_h + roi_start_h);
              int wend = ceil(
                  static_cast<T>(pw + 1) * bin_size_w + roi_start_w);
  
              // Add roi offsets and clip to input boundaries
              hstart = min(max(hstart, 0), height);
              wstart = min(max(wstart, 0), width);
              hend = min(max(hend, 0), height);
              wend = min(max(wend, 0), width);
              bool is_empty = (hend <= hstart) || (wend <= wstart);
  
              // Compute c at bottom
              int gh = floor(
                  static_cast<T>(ph) * group_size / pooled_height);
              int gw = floor(
                  static_cast<T>(pw) * group_size / pooled_width);
              gh = min(max(gh, 0), group_size - 1);
              gw = min(max(gw, 0), group_size - 1);
              int c = (ctop * group_size + gh) * group_size + gw;
  
              int data_offset = (roi_batch_ind * channel + c) * height * width;
              T out_sum = 0;
              for (int h = hstart; h < hend; ++h){
                for (int w = wstart; w < wend; ++w){
                   int bottom_index = h * width + w;
                   out_sum += bottom_data[data_offset + bottom_index];
                }
              }
  
              T bin_area = (hend - hstart) * (wend - wstart);
              top_data = is_empty? (T) 0. : out_sum / bin_area;
              """,
          "ps_roi_average_pooling_2d_fwd",
      )(
          bottom_data,
          bottom_rois,
          bottom_roi_indices,
          self.spatial_scale,
          channel,
          height,
          width,
          out_c,
          self.out_h,
          self.out_w,
          self.group_size,
          top_data,
      )
  
      return (top_data,)
  
file_path: chainercv/chainercv/functions/ps_roi_average_pooling_2d.py
imports: from __future__ import division
  import numbers
  import numpy
  import six
  import chainer
  from chainer.backends import cuda
  from chainer import function
  from chainer.utils import type_check
label_desc: Use image node_id 4 for calling the PSROIAveragePooling2D obj's underlying member method code with example usage: obj.forward_gpu(inputs) and returns: top_data