umer1995 commited on
Commit
bd99637
·
verified ·
1 Parent(s): f0a4e91

Fix fp8 stream: bf16 assign then in-place float8 cast + progress

Browse files
Files changed (1) hide show
  1. app.py +43 -29
app.py CHANGED
@@ -141,7 +141,7 @@ MEM_MODE = (
141
  os.environ.get("NFA_FUN_CN_MEM_MODE") or "model_cpu_offload_and_qfloat8"
142
  ).strip()
143
  # Abort CPU load if Fun CN not ready — do not thrash 35+ min again.
144
- LOAD_DEADLINE_SEC = int(os.environ.get("NFA_FUN_CN_LOAD_DEADLINE_SEC") or "480")
145
 
146
  CONFIG_PATH = APP_DIR / "config" / "flux2_control.yaml"
147
  MODEL_DIR = Path(os.environ.get("NFA_FLUX2_MOUNT") or "/data/FLUX.2-dev")
@@ -282,18 +282,31 @@ def _fp8_dtype_for_key(key: str) -> torch.dtype:
282
 
283
 
284
  def _set_tensor(model: torch.nn.Module, key: str, tensor: torch.Tensor) -> None:
 
 
 
 
 
285
  from accelerate.utils import set_module_tensor_to_device
286
 
287
- target = _fp8_dtype_for_key(key)
288
- # float8 cast must go through a float dtype first on some builds
289
- if target == torch.float8_e4m3fn and tensor.dtype not in (
290
- torch.float8_e4m3fn,
291
- torch.float8_e5m2,
292
- ):
293
- value = tensor.detach().to(dtype=torch.bfloat16).to(dtype=target)
294
- else:
295
- value = tensor.detach().to(dtype=target)
296
- set_module_tensor_to_device(model, key, device="cpu", value=value, dtype=target)
 
 
 
 
 
 
 
 
297
 
298
 
299
  def _stream_shards_into_model(
@@ -303,7 +316,7 @@ def _stream_shards_into_model(
303
  label: str,
304
  ) -> None:
305
  """Load one safetensors shard at a time → fp8; never accumulate full bf16."""
306
- from safetensors import safe_open
307
 
308
  model_sd = model.state_dict()
309
  loaded = 0
@@ -315,23 +328,24 @@ def _stream_shards_into_model(
315
  f"rss_max≈{_rss_gb():.1f}GB path={Path(path).name}",
316
  flush=True,
317
  )
318
- with safe_open(path, framework="pt", device="cpu") as f:
319
- for key in f.keys():
320
- if key not in model_sd:
321
- skipped += 1
322
- continue
323
- tensor = f.get_tensor(key)
324
- if tuple(tensor.shape) != tuple(model_sd[key].shape):
325
- print(
326
- f"[nfa-fun-cn] skip size mismatch {key} "
327
- f"{tuple(tensor.shape)} vs {tuple(model_sd[key].shape)}",
328
- flush=True,
329
- )
330
- skipped += 1
331
- continue
332
- _set_tensor(model, key, tensor)
333
- loaded += 1
334
- del tensor
 
335
  gc.collect()
336
  print(
337
  f"[nfa-fun-cn] {label} stream done loaded={loaded} skipped={skipped} "
 
141
  os.environ.get("NFA_FUN_CN_MEM_MODE") or "model_cpu_offload_and_qfloat8"
142
  ).strip()
143
  # Abort CPU load if Fun CN not ready — do not thrash 35+ min again.
144
+ LOAD_DEADLINE_SEC = int(os.environ.get("NFA_FUN_CN_LOAD_DEADLINE_SEC") or "900")
145
 
146
  CONFIG_PATH = APP_DIR / "config" / "flux2_control.yaml"
147
  MODEL_DIR = Path(os.environ.get("NFA_FLUX2_MOUNT") or "/data/FLUX.2-dev")
 
282
 
283
 
284
  def _set_tensor(model: torch.nn.Module, key: str, tensor: torch.Tensor) -> None:
285
+ """Materialize on CPU as bf16, then in-place cast to float8 when allowed.
286
+
287
+ Direct float8 via set_module_tensor_to_device hung on ZeroGPU CPU; bf16
288
+ assign + ``param.data = param.data.to(float8)`` is the stable path.
289
+ """
290
  from accelerate.utils import set_module_tensor_to_device
291
 
292
+ value = tensor.detach().to(dtype=WEIGHT_DTYPE)
293
+ set_module_tensor_to_device(
294
+ model, key, device="cpu", value=value, dtype=WEIGHT_DTYPE
295
+ )
296
+ del value
297
+ if _fp8_dtype_for_key(key) != torch.float8_e4m3fn:
298
+ return
299
+ # Walk to the Parameter and cast storage in-place (frees bf16 bits).
300
+ mod: torch.nn.Module = model
301
+ parts = key.split(".")
302
+ for p in parts[:-1]:
303
+ mod = getattr(mod, p)
304
+ leaf = parts[-1]
305
+ param = getattr(mod, leaf)
306
+ if isinstance(param, torch.nn.Parameter):
307
+ param.data = param.data.to(torch.float8_e4m3fn)
308
+ elif isinstance(param, torch.Tensor):
309
+ setattr(mod, leaf, param.to(torch.float8_e4m3fn))
310
 
311
 
312
  def _stream_shards_into_model(
 
316
  label: str,
317
  ) -> None:
318
  """Load one safetensors shard at a time → fp8; never accumulate full bf16."""
319
+ from safetensors.torch import load_file
320
 
321
  model_sd = model.state_dict()
322
  loaded = 0
 
328
  f"rss_max≈{_rss_gb():.1f}GB path={Path(path).name}",
329
  flush=True,
330
  )
331
+ sd = load_file(path, device="cpu")
332
+ n_keys = len(sd)
333
+ for j, (key, tensor) in enumerate(sd.items()):
334
+ if key not in model_sd:
335
+ skipped += 1
336
+ continue
337
+ if tuple(tensor.shape) != tuple(model_sd[key].shape):
338
+ skipped += 1
339
+ continue
340
+ _set_tensor(model, key, tensor)
341
+ loaded += 1
342
+ if (j + 1) % 200 == 0 or (j + 1) == n_keys:
343
+ print(
344
+ f"[nfa-fun-cn] {label} shard {i+1} keys {j+1}/{n_keys} "
345
+ f"loaded={loaded} rss_max≈{_rss_gb():.1f}GB",
346
+ flush=True,
347
+ )
348
+ del sd
349
  gc.collect()
350
  print(
351
  f"[nfa-fun-cn] {label} stream done loaded={loaded} skipped={skipped} "