Compare commits

...

10 Commits

Author SHA1 Message Date
47b9ac1071 Patch: v0.20.3 2023-06-08 12:10:54 -04:00
d37b93e679 Reset dataloader end_of_datalaoder at each iter (#1562) 2023-06-08 12:09:50 -04:00
966b6b057d [doc build] Use secrets (#1551) 2023-06-08 09:18:30 -04:00
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
12 changed files with 92 additions and 14 deletions

View File

@ -15,3 +15,4 @@ jobs:
package: accelerate
secrets:
token: ${{ secrets.HUGGINGFACE_PUSH }}
hf_token: ${{ secrets.HF_DOC_BUILD_PUSH }}

View File

@ -1,13 +1,14 @@
name: Delete dev documentation
name: Delete doc comment
on:
pull_request:
types: [ closed ]
workflow_run:
workflows: ["Delete doc comment trigger"]
types:
- completed
jobs:
delete:
uses: huggingface/doc-builder/.github/workflows/delete_doc_comment.yml@main
with:
pr_number: ${{ github.event.number }}
package: accelerate
secrets:
comment_bot_token: ${{ secrets.COMMENT_BOT_TOKEN }}

View File

@ -0,0 +1,12 @@
name: Delete doc comment trigger
on:
pull_request:
types: [ closed ]
jobs:
delete:
uses: huggingface/doc-builder/.github/workflows/delete_doc_comment_trigger.yml@main
with:
pr_number: ${{ github.event.number }}

View File

@ -0,0 +1,16 @@
name: Upload PR Documentation
on:
workflow_run:
workflows: ["Build PR Documentation"]
types:
- completed
jobs:
build:
uses: huggingface/doc-builder/.github/workflows/upload_pr_documentation.yml@main
with:
package_name: accelerate
secrets:
hf_token: ${{ secrets.HF_DOC_BUILD_PUSH }}
comment_bot_token: ${{ secrets.COMMENT_BOT_TOKEN }}

View File

@ -32,7 +32,7 @@ extras["sagemaker"] = [
setup(
name="accelerate",
version="0.20.0.dev0",
version="0.20.3",
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.3"
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

@ -316,6 +316,10 @@ class DataLoaderStateMixin:
cls.end_of_dataloader = False
cls.remainder = -1
def reset(self):
self.end_of_dataloader = False
self.remainder = -1
class DataLoaderShard(DataLoader, DataLoaderStateMixin):
"""
@ -361,6 +365,7 @@ class DataLoaderShard(DataLoader, DataLoaderStateMixin):
def __iter__(self):
if self.rng_types is not None:
synchronize_rng_states(self.rng_types, self.synchronized_generator)
self.reset()
self.gradient_state._add_dataloader(self)
# We can safely pass because the default is -1
with suppress(Exception):

View File

@ -903,7 +903,9 @@ class GradientState:
self.sync_gradients = True
self.active_dataloader = None
self.dataloader_references = [None]
self.plugin_kwargs = gradient_accumulation_plugin.to_kwargs()
self.plugin_kwargs = (
gradient_accumulation_plugin.to_kwargs() if gradient_accumulation_plugin is not None else {}
)
# Plugin args are different and can be updated
if gradient_accumulation_plugin is not None and self.plugin_kwargs != gradient_accumulation_plugin.to_kwargs():

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."""

View File

@ -19,6 +19,7 @@ from torch.utils.data import BatchSampler, DataLoader, IterableDataset
from accelerate.data_loader import (
BatchSamplerShard,
DataLoaderShard,
IterableDatasetShard,
SkipBatchSampler,
SkipDataLoader,
@ -374,3 +375,12 @@ class DataLoaderTester(unittest.TestCase):
dataloader = DataLoader(list(range(16)), batch_size=4)
new_dataloader = skip_first_batches(dataloader, num_batches=2)
self.assertListEqual([t.tolist() for t in new_dataloader], [[8, 9, 10, 11], [12, 13, 14, 15]])
def test_end_of_dataloader(self):
dataloader = DataLoaderShard(list(range(16)), batch_size=4)
for idx, _ in enumerate(dataloader):
self.assertEqual(dataloader.end_of_dataloader, idx == 3)
# Test it also works on the second iteration
for idx, _ in enumerate(dataloader):
self.assertEqual(dataloader.end_of_dataloader, idx == 3)