class_docstr: Greedy Partitioner
  
  Args:
      sort_by (SortBy): Sort sharding options by storage or perf in
          descending order (i.e., large tables will be placed first).
      balance_modules (bool): Whether to sort by modules first, where
          smaller modules will be sorted first. In effect, this will place
          tables in each module in a balanced way.
code: def _get_host_level_devices(
      _topology: Topology,
  ) -> List[List[DeviceHardware]]:
      num_hosts: int = (
          _topology.world_size // _topology.local_world_size
      )
      host_level_devices: List[List[DeviceHardware]] = []
      for i in range(num_hosts):
          devices_in_host = _topology.devices[
              i
              * _topology.local_world_size : (i + 1)
              * _topology.local_world_size
          ]
          host_level_devices.append(devices_in_host)
      return host_level_devices
  
imports: import copy
  import heapq
  import logging
  from dataclasses import dataclass
  from enum import Enum
  from typing import cast, Dict, List, Optional
  from torchrec.distributed.planner.perf_models import NoopPerfModel
  from torchrec.distributed.planner.types import DeviceHardware, PartitionByType, Partitioner, Perf, PerfModel, PlannerError, PlannerErrorType, ShardingOption, Storage, Topology
  from torchrec.distributed.planner.utils import bytes_to_gb, reset_shard_rank
  from torchrec.distributed.types import ShardingType
label_desc: Use image node_id 6 for calling the GreedyPerfPartitioner obj's underlying member method code with example usage: obj._get_host_level_devices(_topology) and returns: host_level_devices