Sharding NNX models over an arbitraty mesh
blaxbird is a Python library that I am developing and which features a high-level API for building and training Flax NNX models without the usual JAX/Flax verbosity.
The newest version, v0.2.0, adds mesh-based sharding: FSDP, tensor parallelism, expert parallelism, or any combination thereof. Below, I am briefly introducing this feature
using a simple example. You can find the blaxbird on GitHub.
Meshs and partitions
To train a model in parallel in NNX, we need to define three things: a sharding
annotation, a mesh, and a data partition spec. A parameter’s sharding is read directly
from its nnx.with_partitioning annotation. The parallelism strategy is defined in the
model itself, while train_fn needs only a jax.sharding.Mesh and a PartitionSpec for the data axis:
from jax.sharding import Mesh, PartitionSpec as P
from jax.experimental import mesh_utils
from blaxbird import train_fn
mesh = Mesh(mesh_utils.create_device_mesh((4, 2)), ("fsdp", "tp"))
with mesh:
train = train_fn(
fns=(train_step, val_step), mesh=mesh,
data_partition_spec=P("fsdp"), ...
)
train(rng_key, optimizer, train_itr, val_itr) Moving from a single device to a 2D FSDP+TP mesh is a one-line change. Neither train_step/val_step nor the model definition change: the sharding strategy is a
property of the mesh shape and the model’s nnx.with_partitioning annotations.
Reference LLMs
With v0.2.0, I added reference implementations of two open-weight LLMs to showcase distributed training with different kinds of
model/data parallelisms:
- Gemma4: sharded over a 2D mesh (FSDP + TP).
- Qwen3Next: top-2-of-8 sparse MoE over a 3D mesh (FSDP + TP + expert).
You can find them in the examples/llm folder.