code: def forward_gpu(self, inputs):
      bottom_rois, gtop_data = inputs
      channels, height, width = self._bottom_data_shape[1:]
      bottom_diff = cuda.cupy.zeros(
          self._bottom_data_shape, bottom_rois.dtype
      )
  
      cuda.elementwise(
          """
              raw T top_diff, raw int32 argmax_data, int32 num_rois,
              T spatial_scale, int32 channels, int32 height, int32 width,
              int32 pooled_height, int32 pooled_width, raw T bottom_rois
              """,
          "T bottom_diff",
          """
              int w = i % width;
              int h = (i / width) % height;
              int c = (i / (width * height)) % channels;
              int num = i / (width * height * channels);
  
              float gradient = 0;
              // Accumulate gradient over all ROIs that pooled this element
              for (int roi_n = 0; roi_n < num_rois; ++roi_n) {
                  // Skip if ROI's batch index doesn't match num
                  if (num != static_cast<int>(bottom_rois[roi_n * 5])) {
                      continue;
                  }
  
                  int roi_start_w = round(bottom_rois[roi_n * 5 + 1]
                                          * spatial_scale);
                  int roi_start_h = round(bottom_rois[roi_n * 5 + 2]
                                          * spatial_scale);
                  int roi_end_w = round(bottom_rois[roi_n * 5 + 3]
                                        * spatial_scale);
                  int roi_end_h = round(bottom_rois[roi_n * 5 + 4]
                                        * spatial_scale);
  
                  // Skip if ROI doesn't include (h, w)
                  const bool in_roi = (w >= roi_start_w && w <= roi_end_w &&
                                       h >= roi_start_h && h <= roi_end_h);
                  if (!in_roi) {
                      continue;
                  }
  
                  int offset = (roi_n * channels + c) * pooled_height
                               * pooled_width;
  
                  // Compute feasible set of pooled units that could have pooled
                  // this bottom unit
  
                  // Force malformed ROIs to be 1x1
                  int roi_width = max(roi_end_w - roi_start_w + 1, 1);
                  int roi_height = max(roi_end_h - roi_start_h + 1, 1);
  
                  float bin_size_h = static_cast<float>(roi_height)
                                 / static_cast<float>(pooled_height);
                  float bin_size_w = static_cast<float>(roi_width)
                                 / static_cast<float>(pooled_width);
  
                  int phstart = floor(static_cast<float>(h - roi_start_h)
                                      / bin_size_h);
                  int phend = ceil(static_cast<float>(h - roi_start_h + 1)
                                   / bin_size_h);
                  int pwstart = floor(static_cast<float>(w - roi_start_w)
                                      / bin_size_w);
                  int pwend = ceil(static_cast<float>(w - roi_start_w + 1)
                                   / bin_size_w);
  
                  phstart = min(max(phstart, 0), pooled_height);
                  phend = min(max(phend, 0), pooled_height);
                  pwstart = min(max(pwstart, 0), pooled_width);
                  pwend = min(max(pwend, 0), pooled_width);
  
                  for (int ph = phstart; ph < phend; ++ph) {
                      for (int pw = pwstart; pw < pwend; ++pw) {
                          int index_ = ph * pooled_width + pw + offset;
                          if (argmax_data[index_] == (h * width + w)) {
                              gradient += top_diff[index_];
                          }
                      }
                  }
              }
              bottom_diff = gradient;
              """,
          "roi_pooling_2d_bwd",
      )(
          gtop_data,
          self.argmax_data,
          bottom_rois.shape[0],
          self.spatial_scale,
          channels,
          height,
          width,
          self.outh,
          self.outw,
          bottom_rois,
          bottom_diff,
      )
  
      return bottom_diff, None
  
imports: import numpy
  import six
  from chainer.backends import cuda
  from chainer import function_node
  from chainer.utils import type_check
label_desc: Use image node_id 3 for calling the ROIPooling2DGrad obj's underlying member method code with example usage: obj.forward_gpu(inputs) and returns: bottom_diff,  None