Repository navigation
Feat: Activation Checkpointing #154
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
base: master
Are you sure you want to change the base?
Changes from all commits
6a53ba5
902a49d
ef544b5
09fca50
ba99bc8
a91674b
e55c2ad
845608d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
|
|
||
| #include <cstdint> | ||
| #include <optional> | ||
| #include <string_view> | ||
|
|
||
| namespace infini_train::nn { | ||
|
|
||
|
|
@@ -54,6 +55,24 @@ struct MoEConfig { | |
| ExpertImpl expert_impl = ExpertImpl::kSequential; | ||
| }; | ||
|
|
||
| enum class ActivationRecomputeGranularity { | ||
| kNone, // Disable activation recompute. | ||
| kFull, // Recompute full transformer layers. | ||
| kSelective, // Recompute selected transformer submodules. | ||
| }; | ||
|
|
||
| enum class ActivationRecomputeMethod { | ||
| kNone, // Recompute every layer when granularity is full. | ||
| kUniform, // Uniformly divide layers into recompute chunks. | ||
| kBlock, // Recompute only the first N layers in the local chunk/stage. | ||
| }; | ||
|
|
||
| struct ActivationRecomputeOptions { | ||
| ActivationRecomputeGranularity granularity = ActivationRecomputeGranularity::kNone; | ||
| ActivationRecomputeMethod method = ActivationRecomputeMethod::kNone; | ||
| int64_t num_layers = 0; | ||
| }; | ||
|
|
||
| struct TransformerConfig { | ||
| int64_t block_size = 1024; // Max seq_len | ||
| int64_t vocab_size = 50304; // Vocab size | ||
|
|
@@ -87,6 +106,11 @@ struct TransformerConfig { | |
| // Normalization | ||
| float norm_eps = 1e-5f; // epsilon in RMSNorm | ||
|
|
||
| // Activation recomputation, aligned with Megatron-Core TransformerConfig. | ||
| ActivationRecomputeGranularity recompute_granularity = ActivationRecomputeGranularity::kNone; | ||
| ActivationRecomputeMethod recompute_method = ActivationRecomputeMethod::kNone; | ||
| int64_t recompute_num_layers = 0; | ||
|
|
||
| // Inference | ||
| bool use_kv = false; // kv cache | ||
| bool flash = false; // flash attention | ||
|
|
@@ -96,5 +120,10 @@ struct TransformerConfig { | |
|
|
||
| bool UseGQA() const; | ||
| int GetChunkSize() const; | ||
| bool RecomputeEnabled() const; | ||
| }; | ||
|
|
||
| ActivationRecomputeOptions ParseActivationRecomputeOptions(bool enabled, std::string_view granularity, | ||
| std::string_view method, int64_t num_layers); | ||
| void ApplyActivationRecomputeOptions(TransformerConfig *config, const ActivationRecomputeOptions &options); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SetActivationRecomputeConfig() 和 ApplyActivationRecomputeOptions() 都包含对 recompute 配置字段的赋值逻辑,存在一定重复。 建议将参数解析和配置应用分离,例如提供 ParseActivationRecomputeOptions() 返回 ActivationRecomputeOptions,再统一通过 ApplyActivationRecomputeOptions() 写入配置。 这样也可以避免 LLMC 加载路径中先 SetActivationRecomputeConfig()、再 GetActivationRecomputeOptions() 的间接流程。 |
||
| } // namespace infini_train::nn | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #pragma once | ||
|
|
||
| #include <functional> | ||
| #include <memory> | ||
| #include <vector> | ||
|
|
||
| namespace infini_train { | ||
| class Tensor; | ||
| } // namespace infini_train | ||
|
|
||
| namespace infini_train::utils::checkpoint { | ||
|
|
||
| using CheckpointForwardFn | ||
| = std::function<std::vector<std::shared_ptr<Tensor>>(const std::vector<std::shared_ptr<Tensor>> &)>; | ||
|
|
||
| // RNG state preservation is not implemented. Random ops such as Dropout cannot | ||
| // be replayed consistently; preserve_rng_state=true is rejected. | ||
| std::vector<std::shared_ptr<Tensor>> Checkpoint(const CheckpointForwardFn &forward_fn, | ||
| const std::vector<std::shared_ptr<Tensor>> &inputs, | ||
| bool use_reentrant = false, bool preserve_rng_state = false, | ||
| bool determinism_check = true, bool early_stop = true); | ||
|
|
||
| } // namespace infini_train::utils::checkpoint |
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.
本质上是需要一个 2*2=4 种情况的精细控制(with_grad/no_grad x 带引用计数建图/仅传递 requires_grad)。
也可以不单独实现一个 guard,而是给原先的 GradGuard 重载一个带参数 (比如 bool record_context = false) 的构造方式,让 GradGuard 本身能够覆盖这四种情况。
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.
with_grad 下,不管 propagate_requires_grad_ 如何设置,行为都是一样的(带引用计数建图且传递 requires_grad);只有 no_grad 模式下,propagate_requires_grad_ 的值会影响 autograd 的实际行为,所以实际上是 3 种情况的控制?(嵌套 Function::Apply() 时,with_grad + propagate_requires_grad_=false/true 的行为可能不一致,但这本身应该是 bug,修复后应当一致)
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.
确实,这俩不是同级并列的关系,with_grad 开关更主导一些。外层先看 with_grad,然后内层再看 propagate_requires_grad_。相当于是三种