code: def get_embedding_shard_metadata(
      grouped_embedding_configs_per_rank: List[
          List[GroupedEmbeddingConfig]
      ],
  ) -> Tuple[List[List[int]], bool]:
      is_even_sharding: bool = True
      world_size = len(grouped_embedding_configs_per_rank)
  
      def get_even_shard_sizes(
          hash_size: int, world_size: int
      ) -> List[int]:
          block_size: int = math.ceil(hash_size / world_size)
          last_rank: int = hash_size // block_size
  
          expected_even_shard_sizes = [block_size] * last_rank
          if hash_size % world_size != 0:
              expected_even_shard_sizes.append(
                  hash_size - sum(expected_even_shard_sizes)
              )
          return expected_even_shard_sizes
  
      embed_sharding = []
      for table in grouped_embedding_configs_per_rank[0][
          0
      ].embedding_tables:
          embed_sharding_per_feature = []
          total_rows = 0
          sizes = []
          # pyre-ignore [16]: `Optional` has no attribute `shards_metadata`
          for metadata in table.global_metadata.shards_metadata:
              embed_sharding_per_feature.append(
                  metadata.shard_offsets[0]
              )
              total_rows += metadata.shard_sizes[0]
              sizes.append(metadata.shard_sizes[0])
          embed_sharding_per_feature.append(total_rows)
          embed_sharding.extend(
              [embed_sharding_per_feature] * len(table.embedding_names)
          )
          expected_even_sizes = get_even_shard_sizes(
              total_rows, world_size
          )
          if sizes != expected_even_sizes:
              is_even_sharding = False
  
      return (embed_sharding, is_even_sharding)
  
imports: import math
  from typing import Any, cast, Dict, List, Optional, Tuple, TypeVar, Union
  import torch
  import torch.distributed
  from torchrec.distributed.dist_data import EmbeddingsAllToOneReduce, KJTAllToAll, KJTOneToAll, PooledEmbeddingsReduceScatter, VariableBatchPooledEmbeddingsReduceScatter
  from torchrec.distributed.embedding_lookup import GroupedPooledEmbeddingsLookup, InferGroupedPooledEmbeddingsLookup
  from torchrec.distributed.embedding_sharding import BaseEmbeddingDist, BaseEmbeddingLookup, BaseSparseFeaturesDist, bucketize_kjt_before_all2all, EmbeddingSharding, EmbeddingShardingContext, EmbeddingShardingInfo, group_tables
  from torchrec.distributed.embedding_types import BaseGroupedFeatureProcessor, EmbeddingComputeKernel, GroupedEmbeddingConfig, KJTList, ShardedEmbeddingTable
  from torchrec.distributed.types import Awaitable, CommOp, NullShardingContext, QuantizedCommCodecs, ShardedTensorMetadata, ShardingEnv, ShardMetadata
  from torchrec.sparse.jagged_tensor import KeyedJaggedTensor
  from torchrec.streamable import Multistreamable
label_desc: Use image node_id 1 for calling a global function with example usage: get_embedding_shard_metadata(grouped_embedding_configs_per_rank) and returns: embed_sharding,  is_even_sharding, expected_even_shard_sizes