|
37 | 37 | ShardMode, |
38 | 38 | ) |
39 | 39 | from maxtext.layers import initializers, linears, mhc, normalizations, quantizations |
40 | | -from maxtext.layers import nnx_wrappers |
| 40 | +from maxtext.layers import nnx_scan, nnx_wrappers |
41 | 41 | from maxtext.layers.attentions import Attention |
42 | 42 | from maxtext.layers.embeddings import Embed, PositionalEmbedding, attend_on_embedding |
43 | 43 | from maxtext.layers.normalizations import RMSNorm |
@@ -839,94 +839,20 @@ def _create_scanned_layers( |
839 | 839 | **layer_kwargs, |
840 | 840 | ): |
841 | 841 | """Creates a scanned stack of layers using jax.lax.scan for memory-efficient initialization.""" |
842 | | - if length == 0: |
843 | | - return None |
844 | | - scan_axis = self.config.param_scan_axis |
845 | | - |
846 | | - # Fork rngs to get per-layer RNG states for scanning |
847 | | - try: |
848 | | - forked_rngs = rngs.fork(split=length) |
849 | | - except: # pylint: disable=bare-except |
850 | | - pass |
851 | | - |
852 | | - rngs_graphdef, rngs_state = nnx.split(forked_rngs) |
853 | | - |
854 | | - first_rng_state = jax.tree.map(lambda x: x[0], rngs_state) |
855 | | - ref_rngs = nnx.merge(rngs_graphdef, first_rng_state) |
856 | | - ref_layer = decoder_layer_class( |
857 | | - config=self.config, |
858 | | - mesh=self.mesh, |
859 | | - quant=self.quant, |
860 | | - model_mode=self.model_mode, |
861 | | - rngs=ref_rngs, |
862 | | - **layer_kwargs, |
| 842 | + return nnx_scan.create_scanned_layers( |
| 843 | + lambda layer_rngs: decoder_layer_class( |
| 844 | + config=self.config, |
| 845 | + mesh=self.mesh, |
| 846 | + model_mode=self.model_mode, |
| 847 | + quant=self.quant, |
| 848 | + rngs=layer_rngs, |
| 849 | + **layer_kwargs, |
| 850 | + ), |
| 851 | + length=length, |
| 852 | + param_scan_axis=self.config.param_scan_axis, |
| 853 | + metadata_axis_name=metadata_axis_name, |
| 854 | + rngs=rngs, |
863 | 855 | ) |
864 | | - layer_graphdef, _, _ = nnx.split(ref_layer, nnx.Param, ...) |
865 | | - del ref_layer |
866 | | - |
867 | | - def scan_body(carry, rng_state_slice): |
868 | | - layer_rngs = nnx.merge(rngs_graphdef, rng_state_slice) |
869 | | - layer = decoder_layer_class( |
870 | | - config=self.config, |
871 | | - mesh=self.mesh, |
872 | | - quant=self.quant, |
873 | | - model_mode=self.model_mode, |
874 | | - rngs=layer_rngs, |
875 | | - **layer_kwargs, |
876 | | - ) |
877 | | - _, params, rest = nnx.split(layer, nnx.Param, ...) |
878 | | - return carry, (params, rest) |
879 | | - |
880 | | - _, (stacked_params, stacked_rest) = jax.lax.scan(scan_body, None, rngs_state) |
881 | | - |
882 | | - if scan_axis != 0: |
883 | | - stacked_params = jax.tree.map(lambda x: jnp.moveaxis(x, scan_axis, 0), stacked_params) |
884 | | - |
885 | | - def _add_scan_metadata(state, axis): |
886 | | - def _update_leaf(leaf): |
887 | | - if hasattr(leaf, "replace") and hasattr(leaf, "value"): |
888 | | - replace_kwargs = {} |
889 | | - if hasattr(leaf, "get_metadata"): |
890 | | - replace_kwargs.update(leaf.get_metadata()) |
891 | | - |
892 | | - replace_kwargs[nnx.PARTITION_NAME] = metadata_axis_name |
893 | | - replace_kwargs["param_scan_axis"] = axis |
894 | | - |
895 | | - for key in [ |
896 | | - "sharding", |
897 | | - "out_sharding", |
898 | | - "kernel_axes", |
899 | | - "sharding_names", |
900 | | - ]: |
901 | | - val = getattr(leaf, key, None) |
902 | | - if val is None and key in replace_kwargs: |
903 | | - val = replace_kwargs[key] |
904 | | - |
905 | | - if val is not None: |
906 | | - if isinstance(val, str): |
907 | | - val = (val,) |
908 | | - if isinstance(val, tuple): |
909 | | - l = list(val) |
910 | | - # Safely insert the scan axis into the logical axes string |
911 | | - if metadata_axis_name not in l: |
912 | | - insert_idx = min(axis, len(l)) |
913 | | - l.insert(insert_idx, metadata_axis_name) |
914 | | - replace_kwargs[key] = tuple(l) |
915 | | - |
916 | | - return leaf.replace(**replace_kwargs) |
917 | | - return leaf |
918 | | - |
919 | | - # We must use a custom is_leaf to catch the VariableState instances |
920 | | - return jax.tree.map( |
921 | | - _update_leaf, |
922 | | - state, |
923 | | - is_leaf=lambda x: hasattr(x, "replace") and hasattr(x, "value"), |
924 | | - ) |
925 | | - |
926 | | - stacked_params = _add_scan_metadata(stacked_params, scan_axis) |
927 | | - stacked_rest = _add_scan_metadata(stacked_rest, 0) |
928 | | - |
929 | | - return nnx.merge(layer_graphdef, stacked_params, stacked_rest) |
930 | 856 |
|
931 | 857 | def _apply_layer_with_remat(self, layer: nnx.Module, y: jax.Array, policy: Any, prevent_cse: bool, **kwargs): |
932 | 858 | """Helper to cleanly apply jax.checkpoint to a single unscanned layer or block.""" |
|
0 commit comments