       thread_num = 512;
     }
 #endif
-
-    KeBilinearInterpFw<T><<<config.block_per_grid, thread_num, 0,
-                            ctx.cuda_device_context().stream()>>>(
-        input_data, in_h, in_w, n, in_chw, output_data, out_h, out_w, n,
-        out_chw, c, ratio_h, ratio_w, align_corners, align_mode, data_layout);
+    const T align_type_value = (align_mode == 0 && !align_corners) ? 0.5f : 0;
+    if (data_layout == DataLayout::kNCHW) {
+      // get launch 3D config
+      int nc = n * c;
+      platform::GpuLaunchConfig config_3d =
+          GetGpuLaunchConfig3D(ctx.cuda_device_context(), nc, out_h, out_w);
+      KeBilinearInterpNCHWFw<
+          T><<<config_3d.block_per_grid, config_3d.thread_per_block, 0,
+               ctx.cuda_device_context().stream()>>>(
+          input_data, in_h, in_w, output_data, out_h, out_w, nc, ratio_h,
+          ratio_w, align_type_value);
+    } else {
+      int64_t cw = c * out_w;
+      auto interp_divmods = FastDivModForInterpolate(c, out_chw, cw);
+      KeBilinearInterpFw<T><<<config.block_per_grid, thread_num, 0,
+                              ctx.cuda_device_context().stream()>>>(
+          input_data, in_h, in_w, n, in_chw, output_data, out_h, out_w, n,
+          out_chw, c, ratio_h, ratio_w, align_type_value, interp_divmods);
+    }
   } else if ("bicubic" == interp_method) {
 #ifdef __HIPCC__
     constexpr int thread_per_block = 256;

    T w1lambda, h1lambda, w2lambda, h2lambda;
    T src_w = ratio_w * (out_img_idx + align_type_value) - align_type_value;
    T src_h = ratio_h * (out_img_idy + align_type_value) - align_type_value;
    PreCalculatorForInputIndex(&in_img_idx, &in_img_idy, &w_id, &h_id,
                               &w1lambda, &h1lambda, &w2lambda, &h2lambda,
                               src_w, src_h, in_w, in_h);

    // top_left_index is just input_index.
    int input_index = out_id_h * in_chw + channel_id * in_img_size +

      T w1lambda, h1lambda, w2lambda, h2lambda;
      T src_w = ratio_w * (out_img_idx + align_type_value) - align_type_value;
      T src_h = ratio_h * (out_img_idy + align_type_value) - align_type_value;

      PreCalculatorForLinearInterpInputIndex(&in_img_idx, &w_id, &w1lambda,
                                             &w2lambda, src_w, in_w);
      PreCalculatorForLinearInterpInputIndex(&in_img_idy, &h_id, &h1lambda,
                                             &h2lambda, src_h, in_h);

      T* in_pos = &in[out_id_h * in_chw + in_img_idy * in_w * num_channels +
                      in_img_idx * num_channels + channel_id];
