class_docstr: Embedding Storage Usage Estimator
code: def estimate(
      self,
      sharding_options: List[ShardingOption],
      sharder_map: Optional[Dict[str, ModuleSharder[nn.Module]]] = None,
  ) -> None:
      if not sharder_map:
          assert (
              not sharding_options
          ), "sharder_map not provided for sharding_options"
          return
  
      for sharding_option in sharding_options:
          sharder_key = sharder_name(type(sharding_option.module[1]))
          sharder = sharder_map[sharder_key]
  
          caching_ratio = (
              sharding_option.cache_params.load_factor
              if sharding_option.cache_params
              else None
          )
          # TODO: remove after deprecating fused_params in sharder
          if caching_ratio is None:
              caching_ratio = (
                  sharder.fused_params.get(
                      "cache_load_factor"
                  )  # pyre-ignore[16]
                  if hasattr(sharder, "fused_params")
                  and sharder.fused_params
                  else None
              )
  
          num_poolings = (
              cast(
                  List[float],
                  self._constraints[sharding_option.name].num_poolings,
              )
              if self._constraints
              and self._constraints.get(sharding_option.name)
              and self._constraints[sharding_option.name].num_poolings
              else [1.0] * sharding_option.num_inputs
          )
          assert len(num_poolings) == sharding_option.num_inputs
          batch_sizes = (
              cast(
                  List[int],
                  self._constraints[sharding_option.name].batch_sizes,
              )
              if self._constraints
              and self._constraints.get(sharding_option.name)
              and self._constraints[sharding_option.name].batch_sizes
              else [sharding_option.batch_size]
              * sharding_option.num_inputs
          )
  
          shard_storages = calculate_shard_storages(
              sharder=sharder,
              sharding_type=sharding_option.sharding_type,
              tensor=sharding_option.tensor,
              compute_device=self._topology.compute_device,
              compute_kernel=sharding_option.compute_kernel,
              shard_sizes=[
                  shard.size for shard in sharding_option.shards
              ],
              batch_sizes=batch_sizes,
              world_size=self._topology.world_size,
              local_world_size=self._topology.local_world_size,
              input_lengths=sharding_option.input_lengths,
              num_poolings=num_poolings,
              caching_ratio=caching_ratio
              if caching_ratio
              else UVM_CACHING_RATIO,
              is_pooled=sharding_option.is_pooled,
          )
  
          for shard, storage in zip(
              sharding_option.shards, shard_storages
          ):
              shard.storage = storage
  
imports: import logging
  import math
  from typing import cast, Dict, List, Optional, Tuple, Type
  import torch
  import torchrec.optim
  from torch import nn
  from torchrec.distributed.embedding_types import EmbeddingComputeKernel
  from torchrec.distributed.planner.constants import BATCHED_COPY_PERF_FACTOR, BIGINT_DTYPE, DP_ELEMENTWISE_KERNELS_PERF_FACTOR, FULL_BLOCK_EMB_DIM, HALF_BLOCK_PENALTY, kernel_bw_lookup, QUARTER_BLOCK_PENALTY, UVM_CACHING_RATIO, WEIGHTED_KERNEL_MULTIPLIER
  from torchrec.distributed.planner.types import ParameterConstraints, Perf, PlannerError, ShardEstimator, ShardingOption, Storage, Topology
  from torchrec.distributed.planner.utils import prod, sharder_name
  from torchrec.distributed.types import CacheStatistics, CommOp, ModuleSharder, ShardingType
  from torchrec.modules.embedding_modules import EmbeddingBagCollectionInterface
label_desc: Use image node_id 2 for calling the EmbeddingStorageEstimator obj's underlying member method code with example usage: obj.estimate(sharding_options, sharder_map) without return types