Keep the elasticity batch overrides out of the caller's config dict (#8329)
`DeepSpeedConfig` keeps the dict it is handed by reference:
```python
if isinstance(config, dict):
self._param_dict = config
```
#8289 established that parsing must not write back into it — the caller
owns that dict and may reuse it after initialization.
The elasticity branch still does, two lines above the comment that says
otherwise:
```python
self._param_dict[TRAIN_BATCH_SIZE] = final_batch_size
self._param_dict[TRAIN_MICRO_BATCH_SIZE_PER_GPU] = micro_batch_size
self._param_dict[GRADIENT_ACCUMULATION_STEPS] = gradient_accu_steps
# Pass a copy so that user json is unmodified, e.g. for logging
self._initialize_params(copy.copy(self._param_dict))
```
A caller that enables elasticity gets three keys back that it never set.
`print_user_config()` dumps `self._param_dict`, so it then reports them
as though the user had written them.
**It also makes the dict unparseable a second time.** The elasticity
path rejects those keys in the input unless
`ignore_non_elastic_batch_info` is set:
```
One or more batch related parameters were found in your ds_config (...).
These parameters *will not be used* since elastic training is enabled ...
```
The first parse succeeds and injects them; the second parse of the same
dict trips that guard, and its message asks the user to remove three
keys they never wrote.
### The fix
Collect the overrides and apply them to the copy. All three are
top-level keys, so the existing shallow copy keeps them off the caller's
dict.
### Test
`DeepSpeedConfig(config_dict)` twice on an elasticity config, with
`ignore_non_elastic_batch_info` left out so the guard is live:
before
```
parse 1 OK, caller dict gained: ['gradient_accumulation_steps', 'train_batch_size', 'train_micro_batch_size_per_gpu']
parse 2 FAILED: ElasticityConfigError One or more batch related parameters were found in your ds_config ...
```
after
```
parse 1 OK, caller dict gained: nothing
parse 2 OK
```
Parsed values are unchanged either way (`train_batch_size=4 micro=2
gas=2`), so this only removes the write-back.
`test_elasticity_leaves_caller_config_untouched` sits next to #8289's
`test_max_grad_norm_leaves_caller_config_untouched` and covers both
symptoms. On master it fails at
```
AssertionError: assert {'elasticity', 'train_batch_size', 'train_micro_batch_size_per_gpu',
'gradient_accumulation_steps'} == {'elasticity'}
```
```
tests/unit/runtime/test_ds_config_dict.py 27 passed, 5 skipped
tests/unit/elasticity/test_elastic.py 23 passed, 3 skipped
yapf --diff / flake8 clean
```
---------
Signed-off-by: alanhuangyoo <alanhuangyoo@gmail.com>
Signed-off-by: Masahiro Tanaka <tanaka.masahiro@gmail.com>
Co-authored-by: Masahiro Tanaka <tanaka.masahiro@gmail.com>