code: def points_in_boxes_cpu(points, boxes):
      """Find all boxes in which each point is (CPU). The CPU version of
      :meth:`points_in_boxes_all`.
  
      Args:
          points (torch.Tensor): [B, M, 3], [x, y, z] in
              LiDAR/DEPTH coordinate
          boxes (torch.Tensor): [B, T, 7],
              num_valid_boxes <= T, [x, y, z, x_size, y_size, z_size, rz],
              (x, y, z) is the bottom center.
  
      Returns:
          box_idxs_of_pts (torch.Tensor): (B, M, T), default background = 0.
      """
      assert points.shape[0] == boxes.shape[0], (
          "Points and boxes should have the same batch size, "
          f"but got {points.shape[0]} and {boxes.shape[0]}"
      )
      assert boxes.shape[2] == 7, (
          "boxes dimension should be 7, "
          f"but got unexpected shape {boxes.shape[2]}"
      )
      assert points.shape[2] == 3, (
          "points dimension should be 3, "
          f"but got unexpected shape {points.shape[2]}"
      )
      batch_size, num_points, _ = points.shape
      num_boxes = boxes.shape[1]
  
      point_indices = points.new_zeros(
          (batch_size, num_boxes, num_points), dtype=torch.int
      )
      for b in range(batch_size):
          ext_module.points_in_boxes_cpu_forward(
              boxes[b].float().contiguous(),
              points[b].float().contiguous(),
              point_indices[b],
          )
      point_indices = point_indices.transpose(1, 2)
  
      return point_indices
  
imports: import torch
  from ..utils import ext_loader
label_desc: Use image node_id 2 for calling a global function with example usage: points_in_boxes_cpu(points, boxes) and returns: point_indices