Compare commits

...

7 Commits

Author SHA1 Message Date
3915c3d754 Patch: v0.20.2 2023-06-08 09:02:50 -04:00
a1ff1ab076 [core] Fix possibility to passNoneType objects in prepare (#1561)
* add possibility to pass nonetype objects

* adds nice test
2023-06-08 09:01:55 -04:00
99f63d56bf fix the typo when setting the "_accelerator_prepared" attribute (#1560)
* fix the typo when setting the "_accelerator_prepared" attribute

* use the name "_is_accelerate_prepared" instead
2023-06-08 09:01:45 -04:00
15384934d7 Patch: v0.20.1 2023-06-07 14:58:56 -04:00
5a41d49ad1 Fix load_state_dict when there is one device and disk (#1557) 2023-06-07 14:58:28 -04:00
d108a51aaf Avoid double wrapping of all accelerate.prepare objects (#1555)
* Add step reset to free memory

* Check if not Accelerated Optimizer

* Continue

* Another try

* Check the rest

* Try with just check on init

* Change logic based on review

* Update

* Oops very big logic issue!
2023-06-07 14:58:19 -04:00
9765b84f9c Release: v0.20.0 2023-06-07 10:05:15 -04:00
5 changed files with 38 additions and 7 deletions

View File

@ -32,7 +32,7 @@ extras["sagemaker"] = [
setup(
name="accelerate",
version="0.20.0.dev0",
version="0.20.2",
description="Accelerate",
long_description=open("README.md", "r", encoding="utf-8").read(),
long_description_content_type="text/markdown",

View File

@ -1,4 +1,4 @@
__version__ = "0.20.0.dev0"
__version__ = "0.20.2"
from .accelerator import Accelerator
from .big_modeling import (

View File

@ -1197,6 +1197,10 @@ class Accelerator:
if self.distributed_type == DistributedType.FSDP and model_count == 1 and optimizer_present:
result = self._prepare_fsdp(*result)
for item in result:
if item is not None:
setattr(item, "_is_accelerate_prepared", True)
return result if len(result) > 1 else result[0]
def prepare_model(self, model: torch.nn.Module, device_placement: bool = None, evaluation_mode: bool = False):
@ -1691,6 +1695,11 @@ class Accelerator:
>>> data_loader = accelerator.prepare_data_loader(data_loader, device_placement=True)
```
"""
# Ensure we can't double wrap a DataLoader due to `find_batch_size`
if getattr(data_loader, "_is_accelerate_prepared", False):
if data_loader not in self._dataloaders:
self._dataloaders.append(data_loader)
return data_loader
if device_placement is None:
device_placement = self.device_placement if self.distributed_type != DistributedType.TPU else False
prepared_data_loader = prepare_data_loader(
@ -1729,6 +1738,11 @@ class Accelerator:
>>> optimizer = accelerator.prepare_optimizer(optimizer, device_placement=True)
```
"""
# Ensure we can't double wrap an optimizer due to `find_batch_size`
if getattr(optimizer, "_is_accelerate_prepared", False):
if optimizer not in self._optimizers:
self._optimizers.append(optimizer)
return optimizer
if device_placement is None:
device_placement = self.device_placement
optimizer = AcceleratedOptimizer(optimizer, device_placement=device_placement, scaler=self.scaler)
@ -1756,6 +1770,11 @@ class Accelerator:
>>> scheduler = accelerator.prepare_scheduler(scheduler)
```
"""
# Ensure we can't double wrap a scheduler due to `find_batch_size`
if getattr(scheduler, "_is_accelerate_prepared", False):
if scheduler not in self._schedulers:
self._schedulers.append(scheduler)
return scheduler
# We try to find the optimizer associated with `scheduler`, the default is the full list.
optimizer = self._optimizers
for opt in self._optimizers:
@ -2546,7 +2565,7 @@ class Accelerator:
def free_memory(self):
"""
Will release all references to the internal objects stored and call the garbage collector. You should call this
method between two trainings with different models/optimizers.
method between two trainings with different models/optimizers. Also will reset `Accelerator.step` to 0.
Example:
@ -2565,6 +2584,7 @@ class Accelerator:
self._models = []
self._dataloaders = []
self.deepspeed_engine_wrapped = None
self.step = 0
release_memory()
def clear(self):

View File

@ -941,12 +941,11 @@ def load_state_dict(checkpoint_file, device_map=None):
if device_map is None:
return safe_load_file(checkpoint_file)
else:
devices = list(set(device_map.values()) - {"disk"})
# if we only have one device we can load everything directly
if len(devices) == 1:
return safe_load_file(checkpoint_file, device=devices[0])
if len(set(device_map.values())) == 1:
return safe_load_file(checkpoint_file, device=list(device_map.values())[0])
devices = list(set(device_map.values()) - {"disk"})
# cpu device should always exist as fallback option
if "cpu" not in devices:
devices.append("cpu")

View File

@ -175,6 +175,18 @@ class AcceleratorTester(AccelerateTestCase):
# mode.class_name is NOT loaded from config
self.assertTrue(model.class_name != model.__class__.__name__)
def test_accelerator_none(self):
"""Just test that passing None to accelerator.prepare() works."""
accelerator = Accelerator()
model, optimizer, scheduler, train_dl, valid_dl = create_components()
dummy_obj = None
# This should work
model, optimizer, scheduler, train_dl, valid_dl, dummy_obj = accelerator.prepare(
model, optimizer, scheduler, train_dl, valid_dl, dummy_obj
)
self.assertTrue(dummy_obj is None)
@slow
def test_accelerator_bnb(self):
"""Tests that the accelerator can be used with the BNB library."""