Validate fp16 dynamic loss scaling parameters are positive (#8050)
## What
`fp16.loss_scale_window` and `fp16.min_loss_scale` drive dynamic loss
scaling but are not validated, so invalid values initialize silently and
fail later during training:
- **`loss_scale_window`** is used as `stable_interval %
self.scale_window` in `DynamicLossScaler.update_scale`
(`deepspeed/runtime/fp16/loss_scaler.py`), so a value of `0` raises
`ZeroDivisionError` mid-training.
- **`min_loss_scale`** is the loss-scale floor (`max(cur_scale /
scale_factor, min_scale)`); a value `<= 0` collapses dynamic loss
scaling.
This is the same class of silent-misconfiguration bug as
`fp16.loss_scale` accepting `inf`, fixed in #7889.
## Change
Add a single Pydantic `mode="before"` field validator on
`DeepSpeedFP16Config` covering both fields. It rejects `bool`,
non-numeric, non-finite (`inf`/`-inf`/`nan`), and non-positive values,
raising a clear `ValidationError` (e.g. `fp16.loss_scale_window must be
> 0`). Following the #7889 review, `mode="before"` runs prior to type
coercion (so `True` is rejected), and `float()` is wrapped in
`try/except` so `[]`/`{}` surface a clear `ValidationError` rather than
a raw `TypeError`.
## Tests
Adds `tests/unit/runtime/test_precision_config_dynamic_scale.py`,
parametrized over both fields:
- invalid: `0, -1, inf, nan, True, [], {}` -> `ValidationError`
- valid: `1, 1000, "2"` -> accepted
```bash
pytest -q tests/unit/runtime/test_precision_config_dynamic_scale.py
```
The validator logic was verified against the full matrix locally; the
import-level test runs under CI.
---------
Signed-off-by: Aryan <aryansputta@gmail.com>
Co-authored-by: Masahiro Tanaka <81312776+tohtana@users.noreply.github.com>