tensorflow/core/common_runtime/ring_alg.cc
// At the beginning of the algorithm initialize a RingField struct for
// every independent field of the tensor.
At the beginning of the algorithm initialize a RingField struct for
every independent field of the tensor.
At the beginning of the algorithm initialize a RingField struct for every independent field of the tensor .
void RingAlg::InitRingField(RingField* rf, int chunk_idx, int subdiv_idx,
                            int field_idx) {
  DCHECK_EQ(field_idx, (chunk_idx * num_subdivs_) + subdiv_idx);
  rf->chunk_idx = chunk_idx;
  rf->subdiv_idx = subdiv_idx;
  rf->sc_idx = field_idx;
  rf->rank = col_params_->subdiv_rank[subdiv_idx];
  rf->second_pass = false;
  rf->action = RF_INIT;
  int recv_from_rank = (rf->rank + (group_size_ - 1)) % group_size_;
  int send_to_rank = (rf->rank + 1) % group_size_;
  rf->recv_dev_idx = col_params_->instance.impl_details
                         .subdiv_permutations[subdiv_idx][recv_from_rank];
  int send_dev_idx = col_params_->instance.impl_details
                         .subdiv_permutations[subdiv_idx][send_to_rank];
  rf->recv_is_remote = !col_params_->group.members[rf->recv_dev_idx].is_local;
  rf->send_is_remote = !col_params_->group.members[send_dev_idx].is_local;
  if (ca_->ChunkBytes(rf->sc_idx) > 0) {
    rf->do_recv = (rf->chunk_idx != rf->rank);
    rf->do_send =
        (rf->rank != ((rf->chunk_idx + (group_size_ - 1)) % group_size_));
  }
  rf->is_final =
      (rf->rank == ((rf->chunk_idx + (group_size_ - 1)) % group_size_));
  if (rf->do_send || rf->do_recv) {
    rf->chunk = ca_->ChunkAlias(rf->sc_idx);
  }
  VLOG(2) << this << " InitRingField " << rf->DebugString() << " chunk "
          << ca_->TBounds(rf->chunk);
}
void RingAlg :: InitRingField ( RingField * rf , int chunk_idx , int subdiv_idx , int field_idx ) { DCHECK_EQ ( field_idx , ( chunk_idx * num_subdivs_ ) + subdiv_idx ) ; rf -> chunk_idx = chunk_idx ; rf -> subdiv_idx = subdiv_idx ; rf -> sc_idx = field_idx ; rf -> rank = col_params_ -> subdiv_rank [ subdiv_idx ] ; rf -> second_pass = false ; rf -> action = RF_INIT ; int recv_from_rank = ( rf -> rank + ( group_size_ - 1 ) ) % group_size_ ; int send_to_rank = ( rf -> rank + 1 ) % group_size_ ; rf -> recv_dev_idx = col_params_ -> instance . impl_details . subdiv_permutations [ subdiv_idx ] [ recv_from_rank ] ; int send_dev_idx = col_params_ -> instance . impl_details . subdiv_permutations [ subdiv_idx ] [ send_to_rank ] ; rf -> recv_is_remote = ! col_params_ -> group . members [ rf -> recv_dev_idx ] . is_local ; rf -> send_is_remote = ! col_params_ -> group . members [ send_dev_idx ] . is_local ; if ( ca_ -> ChunkBytes ( rf -> sc_idx ) > 0 ) { rf -> do_recv = ( rf -> chunk_idx != rf -> rank ) ; rf -> do_send = ( rf -> rank != ( ( rf -> chunk_idx + ( group_size_ - 1 ) ) % group_size_ ) ) ; } rf -> is_final = ( rf -> rank == ( ( rf -> chunk_idx + ( group_size_ - 1 ) ) % group_size_ ) ) ; if ( rf -> do_send || rf -> do_recv ) { rf -> chunk = ca_ -> ChunkAlias ( rf -> sc_idx ) ; } VLOG ( 2 ) << this << " " << rf -> DebugString ( ) << " " << ca_ -> TBounds ( rf -> chunk ) ; }
At the beginning of the algorithm initialize a RingField struct for
every independent field of the tensor.
At the beginning of the algorithm initialize a RingField struct for every independent field of the tensor .
// Note on field indexing: There are group_size_ devices in the // instance, implying the same number of chunks per tensor, where a // chunk is the unit of data transferred in a time step.  However, if // a device can simultaneously send data by 2 or more independent // channels we can speed up the transfer by subdividing chunks and // processing multiple subdivisions at once.  So the actual number // of RingFields is group_size_ * num_subdivs_. // Recv from the device with preceding rank within the subdivision. // In pass 0 we skip Recv when rank = chunk_idx // In pass 0 we skip Send when rank = chunk_idx-1