-
Notifications
You must be signed in to change notification settings - Fork 517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Early Exit Loss and/or Layer Dropout #1076
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/torchtune/1076
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit 69f840c with merge base f3d8d3c (): This comment was automatically generated by Dr. CI and updates every 15 minutes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this PR! I think this would be a great feature for us to support. Left a couple of questions on design, especially how we expose things in TransformerDecoder
. Also, is the idea to eventually support the self-speculative decoding technique as well?
Hi @mostafaelhoushi @ebsmothers @AkshatSh Thanks, |
I am not sure if you would like to support inference optimization techniques in torchtune, but we have implemented self-speculative decoding in gpt-fast here: pytorch-labs/gpt-fast@main...LayerSkip. |
I want to double check, I can't find those 2 branches in this torchtune repo. Are you referring to torchtune repo or another repo? |
apologies, my mistake it is from a different repository: pytorch-labs is there a connection between the 2 branches and the current issue? |
https://github.com/pytorch-labs/gpt-fast/tree/LayerSkip is just a slightly cleaned up fork of https://github.com/pytorch-labs/gpt-fast/tree/ak/layer_skip This PR we are on in torchtune is to implement the training recipe of the same paper. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ebsmothers for your detailed review. Just made a batch of commits and comments to address the feedback.
torchtune/modules/early_exit_loss.py
Outdated
log = utils.get_logger("DEBUG") | ||
|
||
|
||
class LossScaleType(str, Enum): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am personally fine to follow the Callable
approach.
The enum
approach was sort of the convention being followed in the internal codebase I was working on.
If the Callable
approach is sort of the convention for torchtune codebase, I can switch to that. Let me look for some example in the torchtune codebase to follow.
torchtune/modules/early_exit_loss.py
Outdated
log = utils.get_logger("DEBUG") | ||
|
||
|
||
class LossScaleType(str, Enum): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am trying to look for an example to follow but can't find. For example, how can layer_ids_to_loss_scales
determine the scale type?
train_last_layer = cfg_early_exit_loss.get("include_last_layer", True) | ||
verbose = cfg_early_exit_loss.get("verbose", False) | ||
|
||
if cfg_early_exit_loss.curriculum: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 40b7987
train_last_layer = cfg_early_exit_loss.get("include_last_layer", True) | ||
verbose = cfg_early_exit_loss.get("verbose", False) | ||
|
||
if cfg_early_exit_loss.curriculum: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I wanted to use config.instantiate(..)
function call used in other functions like _setup_data()
but I didn't understand how it works.
torchtune/modules/early_exit_loss.py
Outdated
log = utils.get_logger("DEBUG") | ||
|
||
|
||
class LossScaleType(str, Enum): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In test_layer_ids_to_loss_scales
, I just made the PyTest fixture test all the possible values in the enum:
https://github.com/mostafaelhoushi/torchtune/blob/3567a2431dc601efd29220a1ed2826e440fd43be/tests/torchtune/modules/test_early_exit_loss.py#L78C1-L81C6
I think that's one advantage of using enums (to ensure that we test all possible values). In the other solution you described, will we be able to do something similar?
GRADUAL = "gradual" | ||
|
||
|
||
# TODO: create a base curriculum class that can be used for other aspects, e.g., dropout, datasets, etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the base class is EarlyExitCurriculum
. I am thinking that in the future we can have a base class (or Protocol) Curriculum
that can be used for other aspects or modules (dropout, dataset mixture weights, sparsity, etc. ) to change throughout training.
init_process_group(backend="gloo" if cfg.device == "cpu" else "nccl") | ||
if cfg.get("fsdp_cpu_offload", False): | ||
# Utilize all available CPU cores for intra-op parallelism. This provides ~2x | ||
# speed up when benchmarking fused AdamW on CPU | ||
training.set_torch_num_threads() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This is more as a note to myself but) we will need to incorporate the same set of changes from #2108 to get CPU offload + gradient clipping to work together here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few more comments (mostly just responses to open threads). But I think this is just about there, really excited to see it land!
Co-authored-by: ebsmothers <ebs@meta.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @mostafaelhoushi for enabling early exit loss and layer dropout in torchtune! I'm really happy with how it turned out, this is one of my favorite features we've landed (especially given some of the more challenging design aspects you had to work through). Thanks for sticking through it, looking forward to seeing its applications in LayerSkip and elsewhere!
* Llama 3.3 70B (pytorch#2124) * Llama 3.3 readme updates (pytorch#2125) * update configs (pytorch#2107) Co-authored-by: Felipe Mello <felipemello@fb.com> * Reduce logging output for distributed KD (pytorch#2120) * Support Early Exit Loss and/or Layer Dropout (pytorch#1076) Co-authored-by: ebsmothers <ebs@meta.com> * Update checkpointing directory (pytorch#2074) Co-authored-by: Felipe Mello <felipemello@fb.com> Co-authored-by: vancoyendall <vancoykendall@gmail.com> * pass correct arg (pytorch#2127) Co-authored-by: Felipe Mello <felipemello@fb.com> * update configs (pytorch#2128) Co-authored-by: Felipe Mello <felipemello@fb.com> * fix qat_lora_test (pytorch#2131) Co-authored-by: Felipe Mello <felipemello@fb.com> --------- Co-authored-by: Philip Bontrager <pbontrager@gmail.com> Co-authored-by: ebsmothers <ebs@meta.com> Co-authored-by: Felipe Mello <fmellomascarenhas@gmail.com> Co-authored-by: Felipe Mello <felipemello@fb.com> Co-authored-by: Joe Cummings <jrcummings27@gmail.com> Co-authored-by: Mostafa Elhoushi <m.elhoushi@ieee.org> Co-authored-by: vancoyendall <vancoykendall@gmail.com>
* Llama 3.3 70B (pytorch#2124) * Llama 3.3 readme updates (pytorch#2125) * update configs (pytorch#2107) Co-authored-by: Felipe Mello <felipemello@fb.com> * Reduce logging output for distributed KD (pytorch#2120) * Support Early Exit Loss and/or Layer Dropout (pytorch#1076) Co-authored-by: ebsmothers <ebs@meta.com> * Update checkpointing directory (pytorch#2074) Co-authored-by: Felipe Mello <felipemello@fb.com> Co-authored-by: vancoyendall <vancoykendall@gmail.com> * pass correct arg (pytorch#2127) Co-authored-by: Felipe Mello <felipemello@fb.com> * update configs (pytorch#2128) Co-authored-by: Felipe Mello <felipemello@fb.com> * fix qat_lora_test (pytorch#2131) Co-authored-by: Felipe Mello <felipemello@fb.com> --------- Co-authored-by: Philip Bontrager <pbontrager@gmail.com> Co-authored-by: ebsmothers <ebs@meta.com> Co-authored-by: Felipe Mello <fmellomascarenhas@gmail.com> Co-authored-by: Felipe Mello <felipemello@fb.com> Co-authored-by: Joe Cummings <jrcummings27@gmail.com> Co-authored-by: Mostafa Elhoushi <m.elhoushi@ieee.org> Co-authored-by: vancoyendall <vancoykendall@gmail.com>
* Llama 3.3 70B (pytorch#2124) * Llama 3.3 readme updates (pytorch#2125) * update configs (pytorch#2107) Co-authored-by: Felipe Mello <felipemello@fb.com> * Reduce logging output for distributed KD (pytorch#2120) * Support Early Exit Loss and/or Layer Dropout (pytorch#1076) Co-authored-by: ebsmothers <ebs@meta.com> * Update checkpointing directory (pytorch#2074) Co-authored-by: Felipe Mello <felipemello@fb.com> Co-authored-by: vancoyendall <vancoykendall@gmail.com> * pass correct arg (pytorch#2127) Co-authored-by: Felipe Mello <felipemello@fb.com> * update configs (pytorch#2128) Co-authored-by: Felipe Mello <felipemello@fb.com> * fix qat_lora_test (pytorch#2131) Co-authored-by: Felipe Mello <felipemello@fb.com> * guard ckpt imports (pytorch#2133) Co-authored-by: Felipe Mello <felipemello@fb.com> * [bug fix] add parents=True (pytorch#2136) Co-authored-by: Felipe Mello <felipemello@fb.com> * [bug fix] re-add model (pytorch#2135) Co-authored-by: Felipe Mello <felipemello@fb.com> * Update save sizes into GiB (pytorch#2143) * [bug fix] remove config download when source is kaggle (pytorch#2144) Co-authored-by: Felipe Mello <felipemello@fb.com> * [fix] remove "with_suffix" (pytorch#2146) Co-authored-by: Felipe Mello <felipemello@fb.com> * DoRA fixes (pytorch#2139) Co-authored-by: Mircea Mironenco <5738815+mirceamironenco@users.noreply.github.com> * [Fix] Llama 3.2 Vision decoder_trainable flag fixed (pytorch#2150) * Small readme, config updates (pytorch#2157) * Using `FormattedCheckpointFiles` in configs (pytorch#2147) * Move ``get_world_size_and_rank`` to utils (pytorch#2155) * Faster intermediate checkpoints with DCP async save in TorchTune (pytorch#2006) Co-authored-by: Saurabh Mishra <msaurabh@fb.com> * torchdata integration - multi-dataset and streaming support (pytorch#1929) * Allow higher version of lm-eval (pytorch#2165) * Using `FormattedCheckpointFiles` in configs... round 2 (pytorch#2167) * [EZ] Fix set_torch_num_threads in multi-node. (pytorch#2164) --------- Co-authored-by: Philip Bontrager <pbontrager@gmail.com> Co-authored-by: ebsmothers <ebs@meta.com> Co-authored-by: Felipe Mello <fmellomascarenhas@gmail.com> Co-authored-by: Felipe Mello <felipemello@fb.com> Co-authored-by: Joe Cummings <jrcummings27@gmail.com> Co-authored-by: Mostafa Elhoushi <m.elhoushi@ieee.org> Co-authored-by: vancoyendall <vancoykendall@gmail.com> Co-authored-by: Mircea Mironenco <5738815+mirceamironenco@users.noreply.github.com> Co-authored-by: salman <salman.mohammadi@outlook.com> Co-authored-by: Saurabh Mishra <msaurabh@meta.com> Co-authored-by: Saurabh Mishra <msaurabh@fb.com> Co-authored-by: Andrew Ho <andrew.kenneth.ho@gmail.com> Co-authored-by: Eugen Hotaj <eugen_hotaj_91@hotmail.com>
Co-authored-by: ebsmothers <ebs@meta.com>
Co-authored-by: ebsmothers <ebs@meta.com>
Context
What is the purpose of this PR? Is it to
Implements early exit loss and/pr layer dropout to reproduce experiments in various papers like LayerSkip, LITE, LayerDrop, and Progressive Layer Dropping.
Usage
Download Llama2 7B model:
To reproduce experiments of various papers that use early exit loss and/or layer dropout:
Changelog
TransformerDecoder
by refactoring the operations that happen after running all transformer layers that transform last hidden state to a probability vector across all tokens into a separateunembed()
function. This was needed to re-useunembed()
to obtain predictions at intermediate layers, and hence calculate losses at intermediate layers.torchtune/modules/common_utils.py
aslice_str_to_array()
function that can convert numpy-like indexing string into a boolean array.torchtune/modules/early_exit_loss.py
to implement early exit losstorchtune/modules/layer_dropiut.py
to implement layer dropoutTest plan
We will run different variants of this command in the Table below to show different speed ups.
transformers
nightly (to enable early exit speculative decoding as described here):Save this code snippet to a file named
eval_hf.py
Run
eval_hf.py
that benchmarks autoregressive decoding and early exit self-speculative decoding:You should get an output that looks like this:
Hence, LayerSkip's training recipe has enabled LayerSkip's (early exit self-speculative decoding) inference that leads to a speedup of 1.159/0.500 = 2.318x.
We ran different variants of training and obtained the results below. Please note that differences in generation time for different training configurations may be due to different number of tokens generated. Hence, to measure speedup, we need to look at the different generation times for the same training configuration:
Link to Results Spreadsheets
Checklist
pre-commit install
)pytest tests
pytest tests -m integration_test
Future Work
In the future we can:
torchtune/generation/_generation.py
:_generation.py
uses similar code togpt-fast
. We have already implemented early-exit self-speculative decoding on gpt-fast here so it should be straightforward to port to torchtune.early_exit_loss()
function support generic loss preprocessing: different training scripts may perform different pre-processing of logits and labels. We need to refactor training scripts slightly to encapsulate such preprocessing into a function to invoke when calculating early exit loss.early_exit_loss()
function support generic loss functions: support other types of losses like KL divergence loss, or losses represented as lists (as is the case with model'snum_output_chunks
>0).