-
Notifications
You must be signed in to change notification settings - Fork 52
Feat: add named parameters #194
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
Changes from all commits
025efc7
53775fd
f95b66d
77b4a88
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 |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| #pragma once | ||
|
|
||
| #include <cstdint> | ||
| #include <functional> | ||
| #include <memory> | ||
| #include <unordered_map> | ||
| #include <vector> | ||
|
|
@@ -24,6 +25,10 @@ class DistributedOptimizer final : public infini_train::Optimizer { | |
| const std::vector<std::shared_ptr<Module>> &model_chunks, size_t ddp_world_size, | ||
| size_t ddp_rank); | ||
|
|
||
| DistributedOptimizer(OptimizerCreatorNamed base_optimizer_creator, const NamedParameterList &named_parameters, | ||
| const std::vector<std::shared_ptr<Module>> &model_chunks, size_t ddp_world_size, | ||
| size_t ddp_rank); | ||
|
|
||
| void Step() override; | ||
|
|
||
| void ZeroGrad(bool set_to_none = true) override; | ||
|
|
@@ -42,7 +47,10 @@ class DistributedOptimizer final : public infini_train::Optimizer { | |
| virtual float learning_rate() const override; | ||
|
|
||
| private: | ||
| void BuildShardParamsAndBindGrads(); | ||
| using AddShard = std::function<void(const std::shared_ptr<Tensor> &, const std::shared_ptr<Tensor> &)>; | ||
|
|
||
| void InitializeModelChunks(const std::vector<std::shared_ptr<Module>> &model_chunks); | ||
| void BuildShardParamsAndBindGrads(const AddShard &add_shard); | ||
|
|
||
| private: | ||
| // Inherit from DDP model | ||
|
|
@@ -53,9 +61,6 @@ class DistributedOptimizer final : public infini_train::Optimizer { | |
| size_t ddp_world_size_; | ||
| size_t ddp_rank_; | ||
|
|
||
| // shard params | ||
| std::vector<std::shared_ptr<Tensor>> shard_params_; | ||
|
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. 当时加这个成员变量时好像就讨论过,麻烦 @Chamberlain0w0 确认下这样修改是否合适。 我看目前是将 shard_params 作为了 BuildShardParamsAndBindGrads 参数传入,就不需要 DistributedOptimizer 维护了,似乎也更合理,因为 base_optimizer_ 本身已经维护了分片参数,没必要在 DistributedOptimizer 里额外维护一份。
Contributor
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. 确实,这里可以删掉了。 |
||
|
|
||
| // Base optimizer (SGD, Adam and etc.) | ||
| std::shared_ptr<Optimizer> base_optimizer_; | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,24 +28,55 @@ Module::Module(const std::string &type) : type_(type), device_(Device()) {} | |
| const std::string &Module::type() const { return type_; } | ||
|
|
||
| std::vector<std::shared_ptr<Tensor>> Module::Parameters() const { | ||
| const auto &named_parameters = NamedParameters(); | ||
|
|
||
| std::vector<std::shared_ptr<Tensor>> params; | ||
| std::unordered_set<const Tensor *> visited; | ||
| params.reserve(named_parameters.size()); | ||
|
|
||
| for (const auto &[_, param] : named_parameters) { params.emplace_back(param); } | ||
|
|
||
| return params; | ||
| } | ||
|
|
||
| auto AddIfUnvisited = [&](const std::shared_ptr<Tensor> ¶m) { | ||
| if (visited.insert(param.get()).second) { | ||
| params.push_back(param); | ||
| std::vector<std::pair<std::string, std::shared_ptr<Tensor>>> | ||
| Module::NamedParameters(const std::string &prefix, bool recurse, bool remove_duplicate) const { | ||
|
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. Parameters 改成直接调用 NamedParameters 函数。参考: |
||
| std::vector<std::pair<std::string, std::shared_ptr<Tensor>>> named_parameters; | ||
| std::unordered_set<const Tensor *> visited_parameters; | ||
|
|
||
| std::vector<std::pair<std::string, std::shared_ptr<Module>>> named_modules; | ||
|
|
||
| if (recurse) { | ||
| named_modules = const_cast<Module *>(this)->NamedModules( | ||
| /*memory=*/nullptr, prefix, remove_duplicate); | ||
| } else { | ||
| named_modules.emplace_back(prefix, std::const_pointer_cast<Module>(shared_from_this())); | ||
| } | ||
|
|
||
| for (const auto &[module_prefix, module] : named_modules) { | ||
| std::vector<std::pair<std::string, std::shared_ptr<Tensor>>> local_parameters; | ||
| local_parameters.reserve(module->parameters_.size()); | ||
|
|
||
| for (const auto &[name, parameter] : module->parameters_) { | ||
| if (parameter != nullptr) { | ||
| local_parameters.emplace_back(name, parameter); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| // Add parameters of this module | ||
| for (const auto &[_, param] : parameters_) { AddIfUnvisited(param); } | ||
| std::sort(local_parameters.begin(), local_parameters.end(), | ||
| [](const auto &lhs, const auto &rhs) { return lhs.first < rhs.first; }); | ||
|
|
||
| for (const auto &[name, parameter] : local_parameters) { | ||
| if (remove_duplicate && !visited_parameters.insert(parameter.get()).second) { | ||
| continue; | ||
| } | ||
|
|
||
| const std::string full_name = module_prefix.empty() ? name : module_prefix + "." + name; | ||
|
|
||
| // Recursively add parameters of submodules | ||
| for (const auto &[_, module] : modules_) { | ||
| for (const auto ¶m : module->Parameters()) { AddIfUnvisited(param); } | ||
| named_parameters.emplace_back(full_name, parameter); | ||
| } | ||
| } | ||
|
|
||
| return params; | ||
| return named_parameters; | ||
| } | ||
|
|
||
| bool Module::has_parameter(const std::string &name) const { return parameters_.find(name) != parameters_.end(); } | ||
|
|
||
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.
DistributedOptimizer 的改动麻烦 @Chamberlain0w0 也看一下
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.
正确性上没问题,但是构造函数里面同时传入 full_params 和 named_parameters 有点奇怪,这两者并不会同时用到的话,感觉跟普通 Optimizer 构造方式一样,提供两种方式 overload 比较合适。