Skip to content

Commit c67fb13

Browse files
committed
Onboard Flux.2-klein-4B multi-host TPU pod support (TP=4, DP=2, B=16)
1 parent ea2603b commit c67fb13

3 files changed

Lines changed: 22 additions & 20 deletions

File tree

src/maxdiffusion/configs/base_flux2klein.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,6 @@ width: 1024
270270
batch_size: 4
271271
interactive: False
272272

273-
# 4B Architecture Dimensions
274-
depth: 20 # num_single_layers
275-
num_double_layers: 5
276-
hidden_size: 3072
277-
num_attention_heads: 24
273+
# Note: Architecture dimensions (depth, num_double_layers, num_attention_heads) are
274+
# automatically inferred from pretrained_model_name_or_path (transformer/config.json).
278275

src/maxdiffusion/generate_flux2klein.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
from maxdiffusion import pyconfig
3333
from maxdiffusion import max_logging
34+
from maxdiffusion import max_utils
3435
from maxdiffusion.max_utils import create_device_mesh
3536
from maxdiffusion.train_utils import transformer_engine_context
3637

@@ -176,10 +177,18 @@ def main(argv):
176177
repo_id = "black-forest-labs/FLUX.2-klein-9B" if depth_val == 24 else "black-forest-labs/FLUX.2-klein-4B"
177178
max_logging.log(f"Target model detected: {repo_id}")
178179

179-
from huggingface_hub import snapshot_download
180+
import glob
181+
182+
cache_pattern = os.path.expanduser(f"~/.cache/huggingface/hub/models--{repo_id.replace('/', '--')}/snapshots/*")
183+
snapshots = sorted(glob.glob(cache_pattern))
184+
if snapshots:
185+
snapshot_dir = snapshots[-1]
186+
else:
187+
from huggingface_hub import snapshot_download
188+
189+
snapshot_dir = snapshot_download(repo_id=repo_id)
180190

181-
max_logging.log(f"Resolving snapshot directory for model '{repo_id}' from HF Hub...")
182-
snapshot_dir = snapshot_download(repo_id=repo_id)
191+
max_logging.log(f"Host {jax.process_index()} using HF snapshot directory: {snapshot_dir}")
183192
safetensors_path = os.path.join(snapshot_dir, "transformer")
184193
vae_safetensors_path = os.path.join(snapshot_dir, "vae", "diffusion_pytorch_model.safetensors")
185194
text_encoder_path = os.path.join(snapshot_dir, "text_encoder")
@@ -326,7 +335,7 @@ def qwen3_init_fn():
326335
# 8. Load weights on Host CPU
327336
max_logging.log("Loading parameters on Host CPU...")
328337
t_load_start = time.time()
329-
cpu_device = jax.devices("cpu")[0]
338+
cpu_device = jax.local_devices(backend="cpu")[0]
330339
with jax.default_device(cpu_device):
331340
with mesh, nn_partitioning.axis_rules(config.logical_axis_rules):
332341
import flax.linen.spmd as flax_spmd
@@ -355,9 +364,9 @@ def unbox_fn(x):
355364

356365
if config.weights_dtype == "bfloat16":
357366
max_logging.log("Casting JAX parameters to bfloat16 in-place...")
358-
cast_dict_to_bfloat16_inplace(params, device=cpu_device, exclude_keywords=("norm",))
359-
cast_dict_to_bfloat16_inplace(vae_params, device=cpu_device, exclude_keywords=("norm",))
360-
cast_dict_to_bfloat16_inplace(qwen3_params, device=cpu_device, exclude_keywords=("norm",))
367+
cast_dict_to_bfloat16_inplace(params, exclude_keywords=("norm",))
368+
cast_dict_to_bfloat16_inplace(vae_params, exclude_keywords=("norm",))
369+
cast_dict_to_bfloat16_inplace(qwen3_params, exclude_keywords=("norm",))
361370
vae_bn_mean = vae_bn_mean.astype(jnp.bfloat16)
362371
vae_bn_std = vae_bn_std.astype(jnp.bfloat16)
363372

@@ -371,7 +380,7 @@ def unbox_fn(x):
371380
max_logging.log("Putting params on TPU HBM...")
372381
with mesh, nn_partitioning.axis_rules(config.logical_axis_rules):
373382
try:
374-
params = jax.device_put(params, transformer_shardings)
383+
params = jax.tree_util.tree_map(max_utils.device_put_replicated, params, transformer_shardings)
375384
except Exception as err:
376385
max_logging.log("\n❌ jax.device_put(params, transformer_shardings) FAILED!")
377386
flat_p = flax.traverse_util.flatten_dict(params)
@@ -383,9 +392,9 @@ def unbox_fn(x):
383392
sys.stdout.flush()
384393
raise err
385394
max_logging.log("Putting vae_params on TPU HBM...")
386-
vae_params = jax.device_put(vae_params, vae_shardings)
395+
vae_params = jax.tree_util.tree_map(max_utils.device_put_replicated, vae_params, vae_shardings)
387396
max_logging.log("Putting qwen3_params on TPU HBM...")
388-
qwen3_params = jax.device_put(qwen3_params, qwen3_shardings)
397+
qwen3_params = jax.tree_util.tree_map(max_utils.device_put_replicated, qwen3_params, qwen3_shardings)
389398
max_logging.log("All parameters placed on TPU HBM successfully!")
390399
gc.collect()
391400
jax.effects_barrier()

src/maxdiffusion/models/flux/util.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,6 @@ def cast_dict_to_bfloat16_inplace(d, device=None, exclude_keywords=None, parent_
389389
"""
390390
import gc
391391
import jax.numpy as jnp
392-
import jax
393392

394393
for k, v in list(d.items()):
395394
current_key = f"{parent_key}.{k}" if parent_key else str(k)
@@ -399,10 +398,7 @@ def cast_dict_to_bfloat16_inplace(d, device=None, exclude_keywords=None, parent_
399398
is_excluded = exclude_keywords and any(kw.lower() in current_key.lower() for kw in exclude_keywords)
400399
target_dtype = jnp.float32 if is_excluded else jnp.bfloat16
401400

402-
if device is not None:
403-
d[k] = jax.device_put(jnp.array(v, dtype=target_dtype), device=device)
404-
else:
405-
d[k] = jnp.array(v, dtype=target_dtype)
401+
d[k] = v.astype(target_dtype)
406402
if hasattr(d[k], "block_until_ready"):
407403
d[k].block_until_ready()
408404
del v

0 commit comments

Comments
 (0)