|
1 | | -#include <algorithm> |
2 | 1 | #include <cstdlib> |
3 | 2 | #include <format> |
4 | | -#include <iterator> |
5 | 3 | #include <memory> |
6 | 4 | #include <optional> |
7 | 5 | #include <thread> |
@@ -133,36 +131,28 @@ void Train(const nn::parallel::Rank &rank) { |
133 | 131 | const ProcessGroup *tp_pg = nullptr; |
134 | 132 | const ProcessGroup *pp_pg = nullptr; |
135 | 133 |
|
136 | | - auto rank_in_group = [&](const std::vector<int> &group_ranks) { |
137 | | - auto it = std::find(group_ranks.begin(), group_ranks.end(), rank.GlobalRank()); |
138 | | - CHECK(it != group_ranks.end()); |
139 | | - return static_cast<int>(std::distance(group_ranks.begin(), it)); |
140 | | - }; |
141 | | - |
142 | 134 | if (rank.IsParallel()) { |
143 | 135 | auto parallel_device_type |
144 | 136 | = (FLAGS_device == kDeviceMACA) ? Device::DeviceType::kMACA : Device::DeviceType::kCUDA; |
145 | 137 | device = Device(parallel_device_type, rank.thread_rank()); |
146 | 138 |
|
147 | | - // NOTE(dcj): On MACA, defer ProcessGroup creation until AFTER the model |
148 | | - // has been uploaded to the device. MCCL init registers internal P2P |
149 | | - // buffers that leave stale read-only mappings in the address ranges |
150 | | - // mcMalloc later hands out; allocating the model first keeps it in a |
151 | | - // P2P-clean region of the VA space and avoids the "Writing to readonly |
152 | | - // page" race on multi-thread DDP. |
153 | | - // |
154 | | - // Compute the in-group ranks now so model loading (which reads |
155 | | - // nn::parallel::tp_rank) gets the correct shard. |
| 139 | + auto *pg_factory = ProcessGroupFactory::Instance(device.type()); |
156 | 140 | if (ddp_world_size > 1) { |
157 | | - ddp_rank = rank_in_group(GetDataParallelGroupRanks(rank.GlobalRank())); |
| 141 | + ddp_pg = pg_factory->GetOrCreate(GetDataParallelProcessGroupName(rank.GlobalRank()), |
| 142 | + GetDataParallelGroupRanks(rank.GlobalRank())); |
| 143 | + ddp_rank = ddp_pg->GetGroupRank(rank.GlobalRank()); |
158 | 144 | } |
159 | 145 | if (tp_world_size > 1) { |
160 | | - tp_rank = rank_in_group(GetTensorParallelGroupRanks(rank.GlobalRank())); |
| 146 | + tp_pg = pg_factory->GetOrCreate(GetTensorParallelProcessGroupName(rank.GlobalRank()), |
| 147 | + GetTensorParallelGroupRanks(rank.GlobalRank())); |
| 148 | + tp_rank = tp_pg->GetGroupRank(rank.GlobalRank()); |
161 | 149 | // NOTE(zbl): Reserved for VocabParallelEmbedding |
162 | 150 | nn::parallel::tp_rank = tp_rank; |
163 | 151 | } |
164 | 152 | if (pp_world_size > 1) { |
165 | | - pp_rank = rank_in_group(GetPipelineParallelGroupRanks(rank.GlobalRank())); |
| 153 | + pp_pg = pg_factory->GetOrCreate(GetPipelineParallelProcessGroupName(rank.GlobalRank()), |
| 154 | + GetPipelineParallelGroupRanks(rank.GlobalRank())); |
| 155 | + pp_rank = pp_pg->GetGroupRank(rank.GlobalRank()); |
166 | 156 | nn::parallel::pp_rank = pp_rank; |
167 | 157 | } |
168 | 158 | } else { |
@@ -197,22 +187,6 @@ void Train(const nn::parallel::Rank &rank) { |
197 | 187 |
|
198 | 188 | model->To(device); |
199 | 189 |
|
200 | | - if (rank.IsParallel()) { |
201 | | - auto *pg_factory = ProcessGroupFactory::Instance(device.type()); |
202 | | - if (ddp_world_size > 1) { |
203 | | - ddp_pg = pg_factory->GetOrCreate(GetDataParallelProcessGroupName(rank.GlobalRank()), |
204 | | - GetDataParallelGroupRanks(rank.GlobalRank())); |
205 | | - } |
206 | | - if (tp_world_size > 1) { |
207 | | - tp_pg = pg_factory->GetOrCreate(GetTensorParallelProcessGroupName(rank.GlobalRank()), |
208 | | - GetTensorParallelGroupRanks(rank.GlobalRank())); |
209 | | - } |
210 | | - if (pp_world_size > 1) { |
211 | | - pp_pg = pg_factory->GetOrCreate(GetPipelineParallelProcessGroupName(rank.GlobalRank()), |
212 | | - GetPipelineParallelGroupRanks(rank.GlobalRank())); |
213 | | - } |
214 | | - } |
215 | | - |
216 | 190 | utils::PrecisionChecker::BuildNameMap(model.get()); |
217 | 191 |
|
218 | 192 | // Apply LoRA using GetLoRAModel (in-place injection) |
|
0 commit comments