Constructs a device mesh. If `mesh_shape` is specified as a `HybridMeshShape`, we use the `ici_mesh_shape` and `dcn_mesh_shape` directly to construct the mesh. If `mesh_shape` is specified as a `MeshShape`, we first determine whether we are running in a TPU or GPU environment.
(
mesh_shape: Union[MeshShape, HybridMeshShape],
*,
devices: Optional[Sequence[Any]] = None,
)
| 1765 | a[a_i + 1, a_j + 1], |
| 1766 | a[a_i + 1, a_j], |
| 1767 | ] |
| 1768 | ) |
| 1769 | else: |
| 1770 | raise ValueError(f"The target mesh shape {shape} is not implemented.") |
| 1771 | return np.reshape(np.array(b), shape) |
| 1772 | |
| 1773 | |
| 1774 | def _maybe_get_special_mesh( |
| 1775 | mesh_shape: MeshShape, *, devices: np.ndarray |
| 1776 | ) -> Optional[tuple[int, int]]: |
| 1777 | """Checks if any of the special mesh shapes are applicable.""" |
| 1778 | if int(np.prod(mesh_shape)) != 256: |
| 1779 | return None |
| 1780 | if getattr(devices[0], "device_kind", None) not in [ |
| 1781 | "TPU v5e", |
| 1782 | "TPU v6e", |
| 1783 | "TPU v6 lite", |
| 1784 | "TPU v5 lite", |
| 1785 | ]: |
| 1786 | return None |
| 1787 | |
| 1788 | filtered_mesh = tuple(filter(lambda x: x != 1, mesh_shape)) |
| 1789 | target_shapes = [(64, 4), (32, 8)] |
| 1790 | return None if filtered_mesh not in target_shapes else filtered_mesh |
| 1791 | |
| 1792 | |
| 1793 | def build_standard_mesh(mesh_shape: MeshShape, *, devices: np.ndarray) -> np.ndarray: |
| 1794 | logging.info("Building device mesh.") |
| 1795 | mesh_shape = infer_mesh_shape(mesh_shape, num_devices=devices.size) |
| 1796 | try: |
| 1797 | if (shape := _maybe_get_special_mesh(mesh_shape, devices=devices)) is not None: |
| 1798 | # If any of the special mesh shapes is applicable, use them. |
| 1799 | mesh = mesh_utils.create_device_mesh([16, 16], devices=devices) |
| 1800 | mesh = _reshape_mesh_to_rings(mesh, shape=shape) |
| 1801 | mesh = mesh.reshape(mesh_shape) |
| 1802 | logging.log_first_n(logging.INFO, "Using custom mesh: %s", 1, str(mesh)) |
| 1803 | return mesh |
| 1804 | return mesh_utils.create_device_mesh( |
| 1805 | mesh_shape, |
| 1806 | devices=devices, |
| 1807 | # Set allow_split_physical_axes to True to split physical axes. |
| 1808 | # Reference: jax.experimental.mesh_utils.create_device_mesh docs. |
| 1809 | allow_split_physical_axes=True, |
| 1810 | ) |
| 1811 | except NotImplementedError as e: |
| 1812 | logging.warning( |
| 1813 | "mesh_utils.create_device_mesh cannot handle shape %s: %s. " |
| 1814 | "Falling back to the naive mesh. Performance may be reduced.", |
| 1815 | mesh_shape, |
| 1816 | e, |
| 1817 | ) |
| 1818 | return devices.reshape(mesh_shape) |
| 1819 | |
| 1820 | |
| 1821 | def create_hybrid_device_mesh( |
| 1822 | mesh_shape: HybridMeshShape, |
| 1823 | *, |
| 1824 | devices: Sequence[Any], |