code: def calculate_shard_storages(
      sharder: ModuleSharder[nn.Module],
      sharding_type: str,
      tensor: torch.Tensor,
      compute_device: str,
      compute_kernel: str,
      shard_sizes: List[List[int]],
      batch_sizes: List[int],
      world_size: int,
      local_world_size: int,
      input_lengths: List[float],
      num_poolings: List[float],
      caching_ratio: float,
      is_pooled: bool,
  ) -> List[Storage]:
      """
      Calculates estimated storage sizes for each sharded tensor, comprised of input,
      output, tensor, gradient, and optimizer sizes.
  
      Args:
          sharder (ModuleSharder[nn.Module]): sharder for module that supports sharding.
          sharding_type (str): provided ShardingType value.
          tensor (torch.Tensor): tensor to be sharded.
          compute_device (str): compute device to be used.
          compute_kernel (str): compute kernel to be used.
          shard_sizes (List[List[int]]): list of dimensions of each sharded tensor.
          batch_sizes (List[int]): batch size for each input feature.
          world_size (int): total number of devices in topology.
          local_world_size (int): total number of devices in host group topology.
          input_lengths (List[float]): average input lengths synonymous with pooling
              factors.
          num_poolings (List[float]): average number of poolings per sample
              (typically 1.0).
          caching_ratio (float): ratio of HBM to DDR memory for UVM caching.
          is_pooled (bool): True if embedding output is pooled (ie. `EmbeddingBag`), False
              if unpooled/sequential (ie. `Embedding`).
  
      Returns:
          List[Storage]: storage object for each device in topology.
      """
  
      input_data_type_size = BIGINT_DTYPE
      output_data_type_size = tensor.element_size()
  
      input_sizes, output_sizes = _calculate_shard_io_sizes(
          sharding_type=sharding_type,
          batch_sizes=batch_sizes,
          world_size=world_size,
          local_world_size=local_world_size,
          input_lengths=input_lengths,
          emb_dim=tensor.shape[1],
          shard_sizes=shard_sizes,
          input_data_type_size=input_data_type_size,
          output_data_type_size=output_data_type_size,
          num_poolings=num_poolings,
          is_pooled=is_pooled,
      )
  
      tensor_storage = sharder.storage_usage(
          tensor, compute_device, compute_kernel
      )
      hbm_storage: int = tensor_storage.get("hbm", 0)
      ddr_storage: int = tensor_storage.get("ddr", 0)
  
      if compute_kernel in {
          EmbeddingComputeKernel.FUSED_UVM_CACHING.value,
          EmbeddingComputeKernel.QUANT_UVM_CACHING.value,
      }:
          hbm_storage = round(ddr_storage * caching_ratio)
  
      optimizer_class = getattr(tensor, "_optimizer_class", None)
  
      hbm_specific_sizes: List[int] = _calculate_storage_specific_sizes(
          storage=hbm_storage,
          shape=tensor.shape,
          shard_sizes=shard_sizes,
          sharding_type=sharding_type,
          optimizer_class=optimizer_class,
      )
      ddr_specific_sizes: List[int] = _calculate_storage_specific_sizes(
          storage=ddr_storage,
          shape=tensor.shape,
          shard_sizes=shard_sizes,
          sharding_type=sharding_type,
          optimizer_class=optimizer_class,
      )
  
      hbm_sizes: List[int] = [
          input_size + output_size + hbm_specific_size
          if compute_device == "cuda"
          else 0
          for input_size, output_size, hbm_specific_size in zip(
              input_sizes,
              output_sizes,
              hbm_specific_sizes,
          )
      ]
      ddr_sizes: List[int] = [
          input_size + output_size + ddr_specific_size
          if compute_device in {"cpu", "mtia"}
          else ddr_specific_size
          for input_size, output_size, ddr_specific_size in zip(
              input_sizes,
              output_sizes,
              ddr_specific_sizes,
          )
      ]
  
      return [
          Storage(
              hbm=hbm_size,
              ddr=ddr_size,
          )
          for hbm_size, ddr_size in zip(hbm_sizes, ddr_sizes)
      ]
  
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 8 for calling a global function with example usage: calculate_shard_storages(sharder, sharding_type, tensor, compute_device, compute_kernel, shard_sizes, batch_sizes, world_size, local_world_size, input_lengths, num_poolings, caching_ratio, is_pooled) and returns: unknown