class_docstr: Utility functions used to preprocess, save, load, partition, etc. the Criteo
  dataset in a binary (numpy) format.
class_docstr_tok: ["Utility","functions","used","to","preprocess",",","save",",","load",",","partition",",","etc",".","the","Criteo","dataset","in","a","binary","(","numpy",")","format","."]
docstr: Given a rank, world_size, and the lengths (number of rows) for a list of files,
  return which files and which portions of those files (represented as row ranges
  - all range indices are inclusive) should be handled by the rank. Each rank
  will be assigned the same number of rows.
  
  The ranges are determined in such a way that each rank deals with large
  continuous ranges of files. This enables each rank to reduce the amount of data
  it needs to read while avoiding seeks.
  
  Args:
      lengths (List[int]): A list of row counts for each file.
      rank (int): rank.
      world_size (int): world size.
  
  Returns:
      output (Tuple[Dict[int, Tuple[int, int]], int]): First item is a mapping of files
      to the range in those files to be handled by the rank. The keys of this dict are indices.
      The second item is the remainder of dataset length / world size.
docstr_tok: ["Given","a","rank",",","world_size",",","and","the","lengths","(","number","of","rows",")","for","a","list","of","files",",","return","which","files","and","which","portions","of","those","files","(","represented","as","row","ranges","-","all","range","indices","are","inclusive",")","should","be","handled","by","the","rank",".","Each","rank","will","be","assigned","the","same","number","of","rows",".","The","ranges","are","determined","in","such","a","way","that","each","rank","deals","with","large","continuous","ranges","of","files",".","This","enables","each","rank","to","reduce","the","amount","of","data","it","needs","to","read","while","avoiding","seeks",".","Args",":","lengths","(","List","[","int","]",")",":","A","list","of","row","counts","for","each","file",".","rank","(","int",")",":","rank",".","world_size","(","int",")",":","world","size",".","Returns",":","output","(","Tuple","[","Dict","[","int",",","Tuple","[","int",",","int","]","]",",","int","]",")",":","First","item","is","a","mapping","of","files","to","the","range","in","those","files","to","be","handled","by","the","rank",".","The","keys","of","this","dict","are","indices",".","The","second","item","is","the","remainder","of","dataset","length","\/","world","size","."]
code: def get_file_row_ranges_and_remainder(
      lengths: List[int],
      rank: int,
      world_size: int,
      start_row: int = 0,
      last_row: Optional[int] = None,
  ) -> Tuple[Dict[int, Tuple[int, int]], int]:
      """
      Given a rank, world_size, and the lengths (number of rows) for a list of files,
      return which files and which portions of those files (represented as row ranges
      - all range indices are inclusive) should be handled by the rank. Each rank
      will be assigned the same number of rows.
  
      The ranges are determined in such a way that each rank deals with large
      continuous ranges of files. This enables each rank to reduce the amount of data
      it needs to read while avoiding seeks.
  
      Args:
          lengths (List[int]): A list of row counts for each file.
          rank (int): rank.
          world_size (int): world size.
  
      Returns:
          output (Tuple[Dict[int, Tuple[int, int]], int]): First item is a mapping of files
          to the range in those files to be handled by the rank. The keys of this dict are indices.
          The second item is the remainder of dataset length / world size.
      """
  
      # All ..._g variables are globals indices (meaning they range from 0 to
      # total_length - 1). All ..._l variables are local indices (meaning they range
      # from 0 to lengths[i] - 1 for the ith file).
      if last_row is None:
          total_length = sum(lengths) - start_row
      else:
          total_length = last_row - start_row + 1
  
      # Global indices that rank is responsible for. All ranges (left, right) are
      # inclusive.
      rows_per_rank = total_length // world_size
      remainder = total_length % world_size
      rows_per_rank = np.array(
          [rows_per_rank for _ in range(world_size)]
      )
      rows_per_rank[:remainder] += 1
      rank_rows_bins_csr = np.cumsum([0] + list(rows_per_rank))
      rank_left_g = rank_rows_bins_csr[rank] + start_row
      rank_right_g = rank_rows_bins_csr[rank + 1] - 1 + start_row
  
      output = {}
  
      # Find where range (rank_left_g, rank_right_g) intersects each file's range.
      file_left_g, file_right_g = -1, -1
      for idx, length in enumerate(lengths):
          file_left_g = file_right_g + 1
          file_right_g = file_left_g + length - 1
  
          # If the ranges overlap.
          if (
              rank_left_g <= file_right_g
              and rank_right_g >= file_left_g
          ):
              overlap_left_g, overlap_right_g = max(
                  rank_left_g, file_left_g
              ), min(rank_right_g, file_right_g)
  
              # Convert overlap in global numbers to (local) numbers specific to the
              # file.
              overlap_left_l = overlap_left_g - file_left_g
              overlap_right_l = overlap_right_g - file_left_g
              output[idx] = (overlap_left_l, overlap_right_l)
  
      return output, remainder
  
imports: import os
  import shutil
  import time
  from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union
  import numpy
  import torch
  import torch.utils.data.datapipes
  from iopath.common.file_io import PathManager, PathManagerFactory
  from pyre_extensions import none_throws
  from torch.utils.data import IterableDataset, IterDataPipe
  from torchrec.datasets.utils import Batch, LoadFiles, PATH_MANAGER_KEY, ReadLinesFromCSV, safe_cast
  from torchrec.sparse.jagged_tensor import KeyedJaggedTensor
label_desc: Use image node_id 3 for calling the BinaryCriteoUtils obj's underlying member method code with example usage: obj.get_file_row_ranges_and_remainder(lengths, rank, world_size, start_row, last_row) and returns: output,  remainder