Repository: huggingface/accelerate
Pull request: Raise error when logging improperly
A user cannot call the logging utility in `Accelerate` without first building the state in some form. This PR introduces an error raising it as such and fixes https://github.com/huggingface/accelerate/issues/1445

Problem statement:
CPU never used when MPS is available, if logger is used beforehand
### System Info

```Shell
- `Accelerate` version: 0.19.0
- Platform: macOS-13.3.1-arm64-arm-64bit
- Python version: 3.11.3
- Numpy version: 1.24.3
- PyTorch version (GPU?): 2.0.1 (False)
- System RAM: 32.00 GB
- `Accelerate` default config:
	- compute_environment: LOCAL_MACHINE
	- distributed_type: NO
	- mixed_precision: no
	- use_cpu: False
	- num_processes: 1
	- machine_rank: 0
	- num_machines: 1
	- rdzv_backend: static
	- same_network: True
	- main_training_function: main
	- downcast_bf16: no
	- tpu_use_cluster: False
	- tpu_use_sudo: False
	- tpu_env: []
	- dynamo_config: {'dynamo_backend': 'INDUCTOR'}
```


### Information

- [ ] The official example scripts
- [X] My own modified scripts

### Tasks

- [X] One of the scripts in the examples/ folder of Accelerate or an officially supported `no_trainer` script in the `examples` folder of the `transformers` repo (such as `run_no_trainer_glue.py`)
- [X] My own task or dataset (give details below)

### Reproduction

### Logger used beforehand

Device is set to MPS, although we set `cpu` to `True`.

```python
from accelerate import Accelerator
from accelerate.logging import get_logger

logger = get_logger(__name__)
logger.warning(f"Starting test")
accelerator = Accelerator(cpu=True)
print(f"Device: {accelerator.state.device}")
```

### Output:

```
Starting test
Device: mps
```

---

### Logger NOT used beforehand

Device is set to CPU, as expected.

```python
from accelerate import Accelerator
from accelerate.logging import get_logger

logger = get_logger(__name__)
# logger.warning(f"Starting test")
accelerator = Accelerator(cpu=True)
print(f"Device: {accelerator.state.device}")
```

### Output:

```
Device: cpu
```

### Expected behavior

I would expect that whenever cpu=True then device should always be CPU. Also, if I pass a certain device it should use that device. I don't see why using the logger beforehand would have any impact on that.

Hints from issue discussion:
The accelerate logger needs to know about your distributed setup when it begins logging, as a result when doing `log()` it spins up an `AcceleratorState`, forcing it to be whatever is in there. For you to do what you would like, the `Accelerator` must be initialized *first* then the logger.

Commit message: Raise error when logging

Patch to review:
diff --git a/src/accelerate/logging.py b/src/accelerate/logging.py
index 902ddf924cd..49d2dbcfe45 100644
--- a/src/accelerate/logging.py
+++ b/src/accelerate/logging.py
@@ -41,6 +41,10 @@ def log(self, level, msg, *args, **kwargs):
         Accepts a new kwarg of `main_process_only`, which will dictate whether it will be logged across all processes
         or only the main executed one. Default is `True` if not passed
         """
+        if PartialState._shared_state == {}:
+            raise RuntimeError(
+                "You must create a `PartialState` through either `PartialState()` or `Accelerator()` before using the logging utility."
+            )
         main_process_only = kwargs.pop("main_process_only", True)
         if self.isEnabledFor(level) and self._should_log(main_process_only):
             msg, kwargs = self.process(msg, kwargs)


Code review comments:
diff_hunk: @@ -41,6 +41,10 @@ def log(self, level, msg, *args, **kwargs):
         Accepts a new kwarg of `main_process_only`, which will dictate whether it will be logged across all processes
         or only the main executed one. Default is `True` if not passed
         """
+        if PartialState._shared_state == {}:
+            raise RuntimeError(
+                "You must create a `PartialState` through either `PartialState()` or `Accelerator()` before using the logging utility."
path: src/accelerate/logging.py
text: @user1:
```suggestion
                "You must initialize the accelerate state by calling either `PartialState()` or `Accelerator()` before using the logging utility."
```