code: def test_rw_uneven_sharding(
      self,
      weight_dtype: torch.dtype,
      uneven_shard_pattern: Tuple[int, int, int, int],
      device: str,
  ) -> None:
      num_embeddings, size0, size1, size2 = uneven_shard_pattern
      size2 = min(size2, num_embeddings - size0 - size1)
      emb_dim = 64
      local_size = 3
      world_size = 3
      batch_size = 4
      local_device = torch.device(
          "cuda:0" if device == "cuda" else device
      )
      mi = create_test_model(
          num_embeddings,
          emb_dim,
          world_size,
          batch_size,
          dense_device=local_device,
          sparse_device=local_device,
          quant_state_dict_split_scale_bias=True,
          weight_dtype=weight_dtype,
          num_features=1,
      )
  
      non_sharded_model = mi.quant_model
      expected_shards = [
          [
              (
                  (0, 0, size0, 64),
                  "rank:0/cpu" if device == "cpu" else "rank:0/cuda:0",
              ),
              (
                  (size0, 0, size1, 64),
                  "rank:0/cpu" if device == "cpu" else "rank:1/cuda:1",
              ),
              (
                  (size0 + size1, 0, size2, 64),
                  "rank:0/cpu" if device == "cpu" else "rank:2/cuda:2",
              ),
          ],
      ]
  
      sharder = TestQuantEBCSharder(
          sharding_type=ShardingType.ROW_WISE.value,
          kernel_type=EmbeddingComputeKernel.QUANT.value,
          shardable_params=[table.name for table in mi.tables],
      )
  
      module_plan = construct_module_sharding_plan(
          non_sharded_model._module.sparse.ebc,
          per_param_sharding={
              "table_0": row_wise(([size0, size1, size2], "cuda")),
          },
          # pyre-ignore
          sharder=sharder,
          local_size=local_size,
          world_size=world_size,
      )
  
      plan = ShardingPlan(plan={"_module.sparse.ebc": module_plan})
  
      sharded_model = shard_qebc(
          mi=mi,
          sharding_type=ShardingType.ROW_WISE,
          device=local_device,
          expected_shards=expected_shards,
          plan=plan,
      )
      inputs = [
          model_input_to_forward_args(inp.to(local_device))
          for inp in prep_inputs(
              mi, world_size, batch_size, long_indices=False
          )
      ]
      sharded_model.load_state_dict(non_sharded_model.state_dict())
  
      # We need this first inference to make all lazy init in forward
      sharded_output = sharded_model(*inputs[0])
      non_sharded_output = non_sharded_model(*inputs[0])
      assert_close(non_sharded_output, sharded_output)
  
      gm: torch.fx.GraphModule = symbolic_trace(sharded_model)
      gm_script = torch.jit.script(gm)
      gm_script_output = gm_script(*inputs[0])
      assert_close(sharded_output, gm_script_output)
  
imports: import math
  import unittest
  from typing import Dict, List, Tuple
  import hypothesis.strategies
  import torch
  from hypothesis import given, settings
  from torchrec import EmbeddingBagConfig, EmbeddingCollection, EmbeddingConfig, KeyedJaggedTensor
  from torchrec.distributed.embedding_types import EmbeddingComputeKernel, ShardingType
  from torchrec.distributed.planner import EmbeddingShardingPlanner, Topology
  from torchrec.distributed.planner.enumerators import EmbeddingEnumerator
  from torchrec.distributed.planner.shard_estimators import EmbeddingPerfEstimator, EmbeddingStorageEstimator
  from torchrec.distributed.quant_embeddingbag import QuantFeatureProcessedEmbeddingBagCollectionSharder
  from torchrec.distributed.quant_state import sharded_tbes_weights_spec, WeightSpec
  from torchrec.distributed.shard import _shard_modules
  from torchrec.distributed.sharding_plan import column_wise, construct_module_sharding_plan, placement, row_wise
  from torchrec.distributed.test_utils.infer_utils import assert_close, assert_weight_spec, create_cw_min_partition_constraints, create_test_model, KJTInputWrapper, model_input_to_forward_args, model_input_to_forward_args_kjt, prep_inputs, quantize, quantize_fpebc, shard_qebc, shard_qec, TestModelInfo, TestQuantEBCSharder
  from torchrec.distributed.test_utils.test_model import ModelInput
  from torchrec.distributed.types import ShardingEnv, ShardingPlan
  from torchrec.fx import symbolic_trace
  from torchrec.modules.embedding_modules import EmbeddingBagCollection
  from torchrec.modules.feature_processor_ import FeatureProcessorsCollection
  from torchrec.modules.fp_embedding_modules import FeatureProcessedEmbeddingBagCollection
label_desc: Use image node_id 8 for calling the InferShardingsTest obj's underlying member method code with example usage: obj.test_rw_uneven_sharding(weight_dtype, uneven_shard_pattern, device) without return types