| 249 | } |
| 250 | |
| 251 | void flushReduceBucket(at::ScalarType scalar_type) override |
| 252 | { |
| 253 | if (!hasKey(reduce_tasks_, scalar_type)) { return; } |
| 254 | |
| 255 | blockCopyEvents(scalar_type); |
| 256 | |
| 257 | // Calculate temporary buffer size for accumulated gradients or |
| 258 | // communication/storage dtype mismatches. |
| 259 | int64_t tmp_recv_numel = 0; |
| 260 | for (const ReduceTask& t : reduce_tasks_.at(scalar_type)) { |
| 261 | auto recv_buf = param_registry_->getParam(t.getDSId()).getGradBuffer(); |
| 262 | int64_t recv_numel = recv_buf.numel(); |
| 263 | bool use_tmp_recv = recv_numel > 0 && (has_acc_grad_.at(t.getDSId()) || |
| 264 | recv_buf.scalar_type() != scalar_type); |
| 265 | if (use_tmp_recv) { tmp_recv_numel += recv_numel; } |
| 266 | } |
| 267 | |
| 268 | // Allocate temporary buffer if needed |
| 269 | at::Tensor tmp_recv_buf = at::Tensor(); |
| 270 | if (tmp_recv_numel > 0) { |
| 271 | at::cuda::CUDAStreamGuard guard(rs_stream_); |
| 272 | tmp_recv_buf = torch::empty({tmp_recv_numel}, |
| 273 | at::TensorOptions().dtype(scalar_type).device(at::kCUDA)); |
| 274 | } |
| 275 | |
| 276 | applyPreDivision(scalar_type); |
| 277 | |
| 278 | // NCCL ReduceScatter operation |
| 279 | ncclGroupStart(); |
| 280 | int64_t offset = 0; |
| 281 | for (const ReduceTask& t : reduce_tasks_.at(scalar_type)) { |
| 282 | auto recv_buf = param_registry_->getParam(t.getDSId()).getGradBuffer(); |
| 283 | bool acc_grad = has_acc_grad_.at(t.getDSId()); |
| 284 | int64_t recv_numel = recv_buf.numel(); |
| 285 | bool use_tmp_recv = |
| 286 | recv_numel > 0 && (acc_grad || recv_buf.scalar_type() != scalar_type); |
| 287 | |
| 288 | if (use_tmp_recv) { |
| 289 | recv_buf = |
| 290 | tmp_recv_buf.index({torch::indexing::Slice(offset, offset + recv_numel)}); |
| 291 | } |
| 292 | |
| 293 | ncclResult_t result = ncclReduceScatter(t.getSendBuf().data_ptr(), |
| 294 | recv_buf.data_ptr(), |
| 295 | recv_numel, |
| 296 | get_nccl_data_type(scalar_type), |
| 297 | getReductionOp(), |
| 298 | nccl_comm_, |
| 299 | rs_stream_); |
| 300 | if (result != ncclSuccess) { throw std::runtime_error("NCCL ReduceScatter failed"); } |
| 301 | |
| 302 | if (use_tmp_recv) { offset += recv_numel; } |
| 303 | } |
| 304 | ncclGroupEnd(); |
| 305 | |
| 306 | // Move temporary receive results into the ZeRO grad buffer. |
| 307 | { |
| 308 | at::cuda::CUDAStreamGuard guard(rs_stream_); |
nothing calls this directly
no test coverage detected