diff --git a/composer/_version.py b/composer/_version.py index a38b61a722..72f97c6d90 100644 --- a/composer/_version.py +++ b/composer/_version.py @@ -3,4 +3,4 @@ """The Composer Version.""" -__version__ = '0.24.0.dev0' +__version__ = '0.24.0' diff --git a/composer/callbacks/eval_output_logging_callback.py b/composer/callbacks/eval_output_logging_callback.py deleted file mode 100644 index 717994413a..0000000000 --- a/composer/callbacks/eval_output_logging_callback.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright 2022 MosaicML Composer authors -# SPDX-License-Identifier: Apache-2.0 - -"""Log model outputs and expected outputs during ICL evaluation.""" - -import warnings -from copy import deepcopy -from typing import Any, Sequence, Union - -import torch - -from composer.core import Callback, State -from composer.loggers import ConsoleLogger, Logger -from composer.utils import VersionedDeprecationWarning, dist - - -class EvalOutputLogging(Callback): - """Logs eval outputs for each sample of each ICL evaluation dataset. - - ICL metrics are required to support caching the model's responses including information on whether model was correct. - Metrics are responsible for returning the results of individual data points in a dictionary of lists. - The callback will log the metric name, the depadded and detokenized input, any data stored in state.metric_outputs, and - any keys from the batch passed into `batch_keys_to_log`. It will do so after every eval batch. - """ - - def __init__(self, log_tokens=False, *args, **kwargs): - warnings.warn( - VersionedDeprecationWarning( - '`InContextLearningMetric` and it\'s subclasses have been deprecated and ' + - 'migrated to MosaicML\'s llm-foundry repo under the llmfoundry.eval.datasets.in_context_learning module: ' - + 'https://github.com/mosaicml/llm-foundry/blob/main/scripts/eval/README.md.' + - 'As EvalOutputLogging only works for ICL metrics, it has been deprecated and ' + - 'will be migrated as well.', - remove_version='0.24.0', - ), - ) - super().__init__(self, *args, **kwargs) - self.log_tokens = log_tokens - self.columns = None - self.name = None - self.rows = [] - - def eval_batch_end(self, state: State, logger: Logger) -> None: - if not isinstance(state.batch, dict): - warnings.warn( - f'''EvalOutputLogging only supports batches that are dictionary. \ - Found batch for type {type(state.batch)}. \ - Not logging eval outputs.''', - ) - return - - assert state.outputs is not None - assert state.metric_outputs is not None - logging_dict: dict[str, Union[list[Any], torch.Tensor, Sequence[torch.Tensor]]] = deepcopy(state.metric_outputs) - - # If batch mode is not generate, outputs will be logits - if state.batch['mode'] == 'generate': - # Outputs are already detokenized - logging_dict['outputs'] = state.outputs - - input_ids = state.batch['input_ids'] - logged_input = [] - assert state.dataloader is not None - - # Depad and decode input_ids - for input_list in input_ids.tolist(): - dataset = state.dataloader.dataset # pyright: ignore[reportGeneralTypeIssues] - depadded_input = [tok for tok in input_list if tok != dataset.pad_tok_id] - logged_input.append(dataset.tokenizer.decode(depadded_input)) - logging_dict['input'] = logged_input - - # Log token indices if toggled - if self.log_tokens: - logging_dict['input_tokens'] = input_ids.tolist() - if not state.batch['mode'] == 'generate': - if isinstance(state.outputs, torch.Tensor): # pyright - logging_dict['label_tokens'] = state.outputs.tolist() - - # Add run_name as a column - run_name_list = [state.run_name for _ in range(0, len(logging_dict['input']))] - logging_dict['run_name'] = run_name_list - - # NOTE: This assumes _any_ tensor logged are tokens to be decoded. - # This might not be true if, for example, logits are logged. - - # Detokenize data in rows - for key, value in logging_dict.items(): - # All types in list are the same - if isinstance(value[0], torch.Tensor): - logging_dict[key] = [ - state.dataloader.dataset.tokenizer.decode(t) # pyright: ignore[reportGeneralTypeIssues] - for t in value - ] - elif isinstance(value[0], list): - if isinstance(value[0][0], torch.Tensor): - tokenizer = state.dataloader.dataset.tokenizer # pyright: ignore[reportGeneralTypeIssues] - logging_dict[key] = [[tokenizer.decode(choice) for choice in t] for t in value] - - # Convert logging_dict from kv pairs of column name and column values to a list of rows - # Example: - # logging_dict = {"a": ["1a", "2a"], "b": ["1b", "2b"]} - # will become - # columns = {"a", "b"}, rows = [["1a", "1b"], ["2a", "2b"]] - columns = list(logging_dict.keys()) - rows = [list(item) for item in zip(*logging_dict.values())] - - assert state.dataloader_label is not None - if not self.name: - # If only running eval, step will be 0 - # If running training, step will be current training step - step = state.timestamp.batch.value - self.name = f'{state.dataloader_label}_step_{step}' - self.columns = columns - self.rows.extend(rows) - - def eval_end(self, state: State, logger: Logger) -> None: - # eval_batch_end will have set these if there is anything to log - if self.name is None or self.columns is None: - return - - list_of_rows = dist.all_gather_object(self.rows) - rows = [row for rows in list_of_rows for row in rows] - for dest_logger in logger.destinations: - if not isinstance(dest_logger, ConsoleLogger): - dest_logger.log_table(self.columns, rows, name=self.name, step=state.timestamp.batch.value) - - self.rows = [] - self.name = None - self.columns = None diff --git a/composer/core/state.py b/composer/core/state.py index 5c429a1cd4..a39a4ae5ac 100644 --- a/composer/core/state.py +++ b/composer/core/state.py @@ -47,7 +47,6 @@ ParallelismConfig, ParallelismType, TPConfig, - VersionedDeprecationWarning, batch_get, batch_set, dist, @@ -896,21 +895,6 @@ def fsdp_state_dict_type(self): def fsdp_sharded_state_dict_enabled(self): return self.fsdp_config is not None and self.fsdp_enabled and self.fsdp_state_dict_type == 'sharded' - @property - def fsdp_device_mesh(self): - warnings.warn(VersionedDeprecationWarning('fsdp_device_mesh is deprecated. Use device_mesh instead.', '0.24')) - return self.device_mesh - - @property - def load_fsdp_monolith_rank0_only(self): - warnings.warn( - VersionedDeprecationWarning( - 'load_fsdp_monolith_rank0_only is deprecated. Use load_monolith_rank0_only instead.', - '0.24', - ), - ) - return self.load_monolith_rank0_only - @property def load_monolith_rank0_only(self): return ( diff --git a/composer/utils/parallelism.py b/composer/utils/parallelism.py index 4dc921b63a..ee0697c15f 100644 --- a/composer/utils/parallelism.py +++ b/composer/utils/parallelism.py @@ -3,15 +3,11 @@ """Parallelism configs.""" -import warnings from dataclasses import dataclass from typing import Any, Optional from torch.distributed._tensor.device_mesh import DeviceMesh -from composer.utils.warnings import VersionedDeprecationWarning - - @dataclass class FSDPConfig: """Configuration for Fully Sharded Data Parallelism (FSDP).""" @@ -26,7 +22,6 @@ class FSDPConfig: cpu_offload: bool = False data_parallel_shard_degree: int = -1 data_parallel_replicate_degree: Optional[int] = None - device_mesh: Optional[DeviceMesh] = None forward_prefetch: bool = False forward_prefetch_limit: int = 1 ignored_modules: Optional[Any] = None @@ -35,7 +30,6 @@ class FSDPConfig: load_monolith_rank0_only: bool = False load_planner: Optional[Any] = None mixed_precision: str = 'DEFAULT' - process_group: Optional[Any] = None save_planner: Optional[Any] = None sharded_ckpt_prefix_dir: str = 'ep{epoch}-ba{batch}' sharding_strategy: str = 'FULL_SHARD' @@ -48,36 +42,6 @@ class FSDPConfig: def create_fsdp_config(fsdp_config: dict[str, Any]): """Modify fsdp_config to set default values for missing keys.""" fsdp_config = {**fsdp_config} # Shallow copy to avoid modifying input - if 'process_group' in fsdp_config: - warnings.warn( - VersionedDeprecationWarning( - 'process_group is deprecated. Please specify `data_parallel_shard_degree` and `data_parallel_replicate_degree` instead.', - remove_version='0.24', - ), - ) - - if 'device_mesh' in fsdp_config: - warnings.warn( - VersionedDeprecationWarning( - 'device_mesh is deprecated. Please specify `data_parallel_shard_degree` and `data_parallel_replicate_degree` instead.', - remove_version='0.24', - ), - ) - if 'data_parallel_shard_degree' in fsdp_config or 'data_parallel_replicate_degree' in fsdp_config: - raise ValueError( - 'Cannot specify both `device_mesh` and `data_parallel_shard_degree` or `data_parallel_replicate_degree`. Please remove `device_mesh`.', - ) - device_mesh = fsdp_config.pop('device_mesh') - if len(device_mesh) == 1: - fsdp_config['data_parallel_shard_degree'] = device_mesh[0] - elif len(device_mesh) == 2: - fsdp_config['data_parallel_replicate_degree'] = device_mesh[0] - fsdp_config['data_parallel_shard_degree'] = device_mesh[1] - else: - raise ValueError( - f'device_mesh must be of length 1 or 2 but received length {len(device_mesh)} with device mesh {device_mesh}.', - ) - return FSDPConfig(**fsdp_config) diff --git a/docker/README.md b/docker/README.md index a0514ecb3d..376e00ba0a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -15,8 +15,8 @@ all dependencies for both NLP and Vision models. They are built on top of the | Composer Version | CUDA Support | Docker Tag | |--------------------|----------------|----------------------------------------------------------------| -| 0.23.5 | Yes | `mosaicml/composer:latest`, `mosaicml/composer:0.23.5` | -| 0.23.5 | No | `mosaicml/composer:latest_cpu`, `mosaicml/composer:0.23.5_cpu` | +| 0.24.0 | Yes | `mosaicml/composer:latest`, `mosaicml/composer:0.24.0` | +| 0.24.0 | No | `mosaicml/composer:latest_cpu`, `mosaicml/composer:0.24.0_cpu` | **Note**: For a lightweight installation, we recommended using a [MosaicML PyTorch Image](#pytorch-images) and manually diff --git a/docker/build_matrix.yaml b/docker/build_matrix.yaml index ee74d12309..a2299071b7 100644 --- a/docker/build_matrix.yaml +++ b/docker/build_matrix.yaml @@ -208,9 +208,9 @@ TORCHVISION_VERSION: 0.16.2 - AWS_OFI_NCCL_VERSION: '' BASE_IMAGE: nvidia/cuda:12.1.1-cudnn8-devel-ubuntu20.04 - COMPOSER_INSTALL_COMMAND: mosaicml[all]==0.23.5 + COMPOSER_INSTALL_COMMAND: mosaicml[all]==0.24.0 CUDA_VERSION: 12.1.1 - IMAGE_NAME: composer-0-23-5 + IMAGE_NAME: composer-0-24-0 MOFED_VERSION: latest-23.10 NVIDIA_REQUIRE_CUDA_OVERRIDE: cuda>=12.1 brand=tesla,driver>=450,driver<451 brand=tesla,driver>=470,driver<471 brand=unknown,driver>=470,driver<471 brand=nvidia,driver>=470,driver<471 brand=nvidiartx,driver>=470,driver<471 @@ -231,15 +231,15 @@ PYTORCH_NIGHTLY_VERSION: '' PYTORCH_VERSION: 2.3.1 TAGS: - - mosaicml/composer:0.23.5 + - mosaicml/composer:0.24.0 - mosaicml/composer:latest TARGET: composer_stage TORCHVISION_VERSION: 0.18.1 - AWS_OFI_NCCL_VERSION: '' BASE_IMAGE: ubuntu:20.04 - COMPOSER_INSTALL_COMMAND: mosaicml[all]==0.23.5 + COMPOSER_INSTALL_COMMAND: mosaicml[all]==0.24.0 CUDA_VERSION: '' - IMAGE_NAME: composer-0-23-5-cpu + IMAGE_NAME: composer-0-24-0-cpu MOFED_VERSION: latest-23.10 NVIDIA_REQUIRE_CUDA_OVERRIDE: '' PYTHON_VERSION: '3.11' @@ -247,7 +247,7 @@ PYTORCH_NIGHTLY_VERSION: '' PYTORCH_VERSION: 2.3.1 TAGS: - - mosaicml/composer:0.23.5_cpu + - mosaicml/composer:0.24.0_cpu - mosaicml/composer:latest_cpu TARGET: composer_stage TORCHVISION_VERSION: 0.18.1 diff --git a/docker/generate_build_matrix.py b/docker/generate_build_matrix.py index 74d9c7fed4..c6668a25c1 100644 --- a/docker/generate_build_matrix.py +++ b/docker/generate_build_matrix.py @@ -231,7 +231,7 @@ def _main(): composer_entries = [] # The `GIT_COMMIT` is a placeholder and Jenkins will substitute it with the actual git commit for the `composer_staging` images - composer_versions = ['0.23.5'] # Only build images for the latest composer version + composer_versions = ['0.24.0'] # Only build images for the latest composer version composer_python_versions = [PRODUCTION_PYTHON_VERSION] # just build composer against the latest for product in itertools.product(composer_python_versions, composer_versions, cuda_options):