At the beginning of the algorithm initialize a RingField struct for every independent field of the tensor.
| 307 | // At the beginning of the algorithm initialize a RingField struct for |
| 308 | // every independent field of the tensor. |
| 309 | void RingAlg::InitRingField(RingField* rf, int chunk_idx, int subdiv_idx, |
| 310 | int field_idx) { |
| 311 | // Note on field indexing: There are group_size_ devices in the |
| 312 | // instance, implying the same number of chunks per tensor, where a |
| 313 | // chunk is the unit of data transferred in a time step. However, if |
| 314 | // a device can simultaneously send data by 2 or more independent |
| 315 | // channels we can speed up the transfer by subdividing chunks and |
| 316 | // processing multiple subdivisions at once. So the actual number |
| 317 | // of RingFields is group_size_ * num_subdivs_. |
| 318 | DCHECK_EQ(field_idx, (chunk_idx * num_subdivs_) + subdiv_idx); |
| 319 | rf->chunk_idx = chunk_idx; |
| 320 | rf->subdiv_idx = subdiv_idx; |
| 321 | rf->sc_idx = field_idx; |
| 322 | rf->rank = col_params_->subdiv_rank[subdiv_idx]; |
| 323 | rf->second_pass = false; |
| 324 | rf->action = RF_INIT; |
| 325 | // Recv from the device with preceding rank within the subdivision. |
| 326 | int recv_from_rank = (rf->rank + (group_size_ - 1)) % group_size_; |
| 327 | int send_to_rank = (rf->rank + 1) % group_size_; |
| 328 | rf->recv_dev_idx = col_params_->instance.impl_details |
| 329 | .subdiv_permutations[subdiv_idx][recv_from_rank]; |
| 330 | int send_dev_idx = col_params_->instance.impl_details |
| 331 | .subdiv_permutations[subdiv_idx][send_to_rank]; |
| 332 | rf->recv_is_remote = !col_params_->task.is_local[rf->recv_dev_idx]; |
| 333 | rf->send_is_remote = !col_params_->task.is_local[send_dev_idx]; |
| 334 | if (ca_->ChunkBytes(rf->sc_idx) > 0) { |
| 335 | // In pass 0 we skip Recv when rank = chunk_idx |
| 336 | rf->do_recv = (rf->chunk_idx != rf->rank); |
| 337 | // In pass 0 we skip Send when rank = chunk_idx-1 |
| 338 | rf->do_send = |
| 339 | (rf->rank != ((rf->chunk_idx + (group_size_ - 1)) % group_size_)); |
| 340 | } |
| 341 | rf->is_final = |
| 342 | (rf->rank == ((rf->chunk_idx + (group_size_ - 1)) % group_size_)); |
| 343 | if (rf->do_send || rf->do_recv) { |
| 344 | rf->chunk = ca_->ChunkAlias(rf->sc_idx); |
| 345 | } |
| 346 | VLOG(2) << this << " InitRingField " << rf->DebugString() << " chunk " |
| 347 | << ca_->TBounds(rf->chunk); |
| 348 | } |
| 349 | |
| 350 | // When a RingField transitions from first to second recompute the |
| 351 | // do_send and do_recv values. |
nothing calls this directly
no test coverage detected