class_docstr: Manage Embedding Weights on CPU and CUDA memory uses a software cache.
  CPU maintains the entire original weight.
  CUDA maintains a fraction of the weights used in the upcoming computation. The row number in CUDA is controlled by `cuda_row_num`.
  During training, GPU needs to transmit embedding rows between CPU and GPU.
  Args:
      weight (torch.Tensor): the weight of the Embedding layer.
      cuda_row_num (int, optional): the number of rows cached in CUDA memory. Defaults to 0.
      buffer_size (int, optional): the number of rows in a data transmitter buffer. Defaults to 50_000.
      pin_weight (bool, optional): use pin memory to store the cpu weight. If set `True`, the cpu memory usage will increase largely. Defaults to False.
      evict_strategy (EvictionStrategy, optional): the eviction strategy. There are two options.
      `EvictionStrategy.LFU`: use the least frequently used cache.
      `EvictionStrategy.DATASET`: use the stats collected from the target dataset. It usually leads to less cpu-gpu communication volume.
      Defaults to EvictionStrategy.DATASET.
class_docstr_tok: ["Manage","Embedding","Weights","on","CPU","and","CUDA","memory","uses","a","software","cache",".","CPU","maintains","the","entire","original","weight",".","CUDA","maintains","a","fraction","of","the","weights","used","in","the","upcoming","computation",".","The","row","number","in","CUDA","is","controlled","by","`","cuda_row_num","`",".","During","training",",","GPU","needs","to","transmit","embedding","rows","between","CPU","and","GPU",".","Args",":","weight","(","torch.Tensor",")",":","the","weight","of","the","Embedding","layer",".","cuda_row_num","(","int",",","optional",")",":","the","number","of","rows","cached","in","CUDA","memory",".","Defaults","to","0.","buffer_size","(","int",",","optional",")",":","the","number","of","rows","in","a","data","transmitter","buffer",".","Defaults","to","50_000",".","pin_weight","(","bool",",","optional",")",":","use","pin","memory","to","store","the","cpu","weight",".","If","set","`","True","`",",","the","cpu","memory","usage","will","increase","largely",".","Defaults","to","False",".","evict_strategy","(","EvictionStrategy",",","optional",")",":","the","eviction","strategy",".","There","are","two","options",".","`","EvictionStrategy.LFU","`",":","use","the","least","frequently","used","cache",".","`","EvictionStrategy.DATASET","`",":","use","the","stats","collected","from","the","target","dataset",".","It","usually","leads","to","less","cpu-gpu","communication","volume",".","Defaults","to","EvictionStrategy.DATASET","."]
docstr: deprecated
  evict one row from cuda to cpu.
  Returns:
  (int) : the slot id be evicted.
docstr_tok: ["deprecated","evict","one","row","from","cuda","to","cpu",".","Returns",":","(","int",")",":","the","slot","id","be","evicted","."]
code: def _evict(self) -> int:
      """
      deprecated
      evict one row from cuda to cpu.
      Returns:
      (int) : the slot id be evicted.
      """
      mask = torch.logical_or(
          torch.isin(self.cached_idx_map, self.evict_backlist),
          self.cached_idx_map == -1,
      )
      buf = self.cached_idx_map[mask].clone()
      idx = torch.nonzero(mask).squeeze(1)
      self.cached_idx_map.index_fill_(0, idx, -1)
      max_row, max_cpu_row_idx = torch.max(self.cached_idx_map, dim=0)
      max_gpu_row_idx = self.cached_idx_map[max_cpu_row_idx]
  
      if max_gpu_row_idx == -1:
          raise RuntimeError("Can not evict a row")
  
      max_gpu_row_idx = max_gpu_row_idx.item()
      max_offset = self.inverted_cached_idx[max_gpu_row_idx]
      # recover
      self.cached_idx_map.index_copy_(0, idx, buf)
  
      with Timer() as timer:
          cuda_tensor = torch.narrow(
              self.cuda_cached_weight.view(-1),
              0,
              max_offset * self.embedding_dim,
              self.embedding_dim,
          ).view(1, self.embedding_dim)
          self.cpu_weight_data(max_gpu_row_idx).data.copy_(cuda_tensor)
  
      # update inverted_cached_idx, min_slot_id is evicted from cuda
      self.cached_idx_map[max_cpu_row_idx] = -1
      if self._evict_strategy == EvictionStrategy.LFU:
          self.freq_cnter[max_cpu_row_idx] = sys.maxsize
      self.inverted_cached_idx[max_gpu_row_idx] = -1
  
      self._cuda_available_row_num += 1
  
      self._cuda_to_cpu_numel += self.embedding_dim
      # self.num_write_back_history[-1] += 1
      return max_cpu_row_idx
  
imports: import sys
  from contextlib import contextmanager
  from enum import Enum
  from typing import List, Optional
  import numpy
  import torch
  from contexttimer import Timer
  from torch.profiler import record_function
  from .copyer import LimitBuffIndexCopyer
label_desc: Use image node_id 16 for calling the CachedParamMgr obj's underlying member method code with example usage: obj._evict() and returns: max_cpu_row_idx