📄 clog_sync.c
字号:
next_adj_rank, CLOG_SYNC_SLAVE_READY, MPI_COMM_WORLD, &status ); /* Set recv_cnt to actual received count of double */ PMPI_Get_count( &status, CLOG_TIME_MPI_TYPE, &recv_cnt ); /* Send&Recv timestamp */ sync_time_start = CLOG_Timer_get(); PMPI_Send( &dummytime, 1, CLOG_TIME_MPI_TYPE, next_adj_rank, CLOG_SYNC_TIME_QUERY, MPI_COMM_WORLD ); PMPI_Recv( &sync_time_esti, 1, CLOG_TIME_MPI_TYPE, next_adj_rank, CLOG_SYNC_TIME_ANSWER, MPI_COMM_WORLD, &status ); sync_time_final = CLOG_Timer_get(); if ( (sync_time_final - sync_time_start) < gpofst_pairs[ gpofst_idx ] ) { gpofst_pairs[ gpofst_idx ] = sync_time_final - sync_time_start; gpofst_pairs[ gpofst_idx+1 ] = 0.5 * ( sync_time_final + sync_time_start ) - sync_time_esti; } best_gp = gpofst_pairs[ gpofst_idx ]; best_ofst = gpofst_pairs[ gpofst_idx+1 ]; gpofst_idx += 2; /* increment to include the recent exchanges */ for ( ii = 0; ii < recv_cnt; ii += 2 ) { gpofst_pairs[ gpofst_idx+ii ] += best_gp; gpofst_pairs[ gpofst_idx+ii+1 ] += best_ofst; } gpofst_idx += recv_cnt; /* total increment = recv_cnt + 2 */ } } else { /* if ( rank_rem != 0 ) */ prev_adj_rank = CLOG_Sync_ring_rank( sync->world_size, sync->root, sync->world_rank - rank_sep ); if ( prev_adj_rank >= 0 ) { /* Recv&Send ready message */ PMPI_Recv( &dummytime, 0, CLOG_TIME_MPI_TYPE, prev_adj_rank, CLOG_SYNC_MASTER_READY, MPI_COMM_WORLD, &status ); /* Send gpofst_pairs[ 0 ... gpofst_idx-1 ] */ send_cnt = gpofst_idx; gpofst_ptr = gpofst_pairs; PMPI_Send( gpofst_ptr, send_cnt, CLOG_TIME_MPI_TYPE, prev_adj_rank, CLOG_SYNC_SLAVE_READY, MPI_COMM_WORLD ); /* Recv&Send timestamp */ PMPI_Recv( &dummytime, 1, CLOG_TIME_MPI_TYPE, prev_adj_rank, CLOG_SYNC_TIME_QUERY, MPI_COMM_WORLD, &status ); sync_time_esti = CLOG_Timer_get(); PMPI_Send( &sync_time_esti, 1, CLOG_TIME_MPI_TYPE, prev_adj_rank, CLOG_SYNC_TIME_ANSWER, MPI_COMM_WORLD ); break; } } /* endof if ( rank_rem == 0 ) */ rank_rem = rank_quot & 1; /* rank_rem = rank_quot % 2; */ rank_quot >>= 1; /* rank_quot /= 2; */ rank_sep <<= 1; /* rank_sep *= 2; */ } /* endof while ( rank_sep < sync->world_size ) */ } /* endof for ( idx < sync->frequency ) */ /* Compute the global time offset based on relative time offset. */ if ( sync->world_rank == sync->root ) { for ( ii = 2*(sync->world_size-1); ii >= 2; ii -= 2 ) { gpofst_pairs[ ii ] = gpofst_pairs[ ii-2 ]; /* gap */ gpofst_pairs[ ii+1 ] = gpofst_pairs[ ii-1 ]; /* offset */ } gpofst_pairs[ 0 ] = 0.0; gpofst_pairs[ 1 ] = 0.0; } PMPI_Scatter( gpofst_pairs, 2, CLOG_TIME_MPI_TYPE, sync->best_gpofst, 2, CLOG_TIME_MPI_TYPE, sync->root, MPI_COMM_WORLD ); if ( gpofst_pairs != NULL ) FREE( gpofst_pairs ); return sync->best_gpofst[1];}/* A scalable O(1), perfectly parallel, algorithm. An alterating neighbor in a ring algorithm that does constant steps. The algorithm is least accurate but perfectly parallel.*/static CLOG_Time_t CLOG_Sync_run_altngbr( CLOG_Sync_t *sync ){ int prev_world_rank, next_world_rank; int ii, idx; int iorder, is_odd_rank; CLOG_Time_t dummytime; CLOG_Time_t sync_time_start, sync_time_final, sync_time_esti; CLOG_Time_t bestgap, bestshift; CLOG_Time_t *gpofst_pairs, best_gpofst[2]; CLOG_Time_t tmp_gp, tmp_ofst, sum_gp, sum_ofst; MPI_Status status; dummytime = 0.0; bestshift = 0.0; /* Set neighbors' world rank */ prev_world_rank = sync->world_rank - 1; if ( prev_world_rank < 0 ) prev_world_rank = sync->world_size - 1; next_world_rank = sync->world_rank + 1; if ( next_world_rank >= sync->world_size ) next_world_rank = 0; PMPI_Barrier( MPI_COMM_WORLD ); PMPI_Barrier( MPI_COMM_WORLD ); /* approximate common starting point */ bestgap = CLOG_SYNC_LARGEST_GAP; for ( idx = 0; idx < sync->frequency; idx++ ) { for ( iorder = sync->world_rank; iorder <= sync->world_rank+1; iorder++ ) { is_odd_rank = iorder % 2; if ( ! is_odd_rank ) { /* Send&Recv ready message */ PMPI_Send( &dummytime, 0, CLOG_TIME_MPI_TYPE, next_world_rank, CLOG_SYNC_MASTER_READY, MPI_COMM_WORLD ); PMPI_Recv( &dummytime, 0, CLOG_TIME_MPI_TYPE, next_world_rank, CLOG_SYNC_SLAVE_READY, MPI_COMM_WORLD, &status ); /* Send&Recv timestamp */ sync_time_start = CLOG_Timer_get(); PMPI_Send( &dummytime, 1, CLOG_TIME_MPI_TYPE, next_world_rank, CLOG_SYNC_TIME_QUERY, MPI_COMM_WORLD ); PMPI_Recv( &sync_time_esti, 1, CLOG_TIME_MPI_TYPE, next_world_rank, CLOG_SYNC_TIME_ANSWER, MPI_COMM_WORLD, &status ); sync_time_final = CLOG_Timer_get(); if ( (sync_time_final - sync_time_start) < bestgap ) { bestgap = sync_time_final - sync_time_start; bestshift = 0.5 * (sync_time_final + sync_time_start) - sync_time_esti; } } else { /* Recv&Send ready message */ PMPI_Recv( &dummytime, 0, CLOG_TIME_MPI_TYPE, prev_world_rank, CLOG_SYNC_MASTER_READY, MPI_COMM_WORLD, &status ); PMPI_Send( &dummytime, 0, CLOG_TIME_MPI_TYPE, prev_world_rank, CLOG_SYNC_SLAVE_READY, MPI_COMM_WORLD ); /* Recv&Send timestamp */ PMPI_Recv( &dummytime, 1, CLOG_TIME_MPI_TYPE, prev_world_rank, CLOG_SYNC_TIME_QUERY, MPI_COMM_WORLD, &status ); sync_time_esti = CLOG_Timer_get(); PMPI_Send( &sync_time_esti, 1, CLOG_TIME_MPI_TYPE, prev_world_rank, CLOG_SYNC_TIME_ANSWER, MPI_COMM_WORLD ); } } } /* endof for ( idx < sync->frequency ) */ best_gpofst[0] = bestgap; best_gpofst[1] = bestshift; if ( sync->root != 0 ) { /* Poor man implementation of MPI_Scan when root =\= 0 */ gpofst_pairs = NULL; if ( sync->world_rank == sync->root ) gpofst_pairs = (CLOG_Time_t *) MALLOC( 2 * sync->world_size * sizeof(CLOG_Time_t) ); PMPI_Gather( best_gpofst, 2, CLOG_TIME_MPI_TYPE, gpofst_pairs, 2, CLOG_TIME_MPI_TYPE, sync->root, MPI_COMM_WORLD ); if ( sync->world_rank == sync->root ) { sum_gp = gpofst_pairs[2*sync->root]; sum_ofst = gpofst_pairs[2*sync->root+1]; gpofst_pairs[2*sync->root] = 0.0; gpofst_pairs[2*sync->root+1] = 0.0; for ( ii = sync->root+1; ii < sync->world_size; ii++ ) { tmp_gp = gpofst_pairs[2*ii]; tmp_ofst = gpofst_pairs[2*ii+1]; gpofst_pairs[2*ii] = sum_gp; gpofst_pairs[2*ii+1] = sum_ofst; sum_gp += tmp_gp; sum_ofst += tmp_ofst; } for ( ii = 0; ii < sync->root; ii++ ) { tmp_gp = gpofst_pairs[2*ii]; tmp_ofst = gpofst_pairs[2*ii+1]; gpofst_pairs[2*ii] = sum_gp; gpofst_pairs[2*ii+1] = sum_ofst; sum_gp += tmp_gp; sum_ofst += tmp_ofst; } } PMPI_Scatter( gpofst_pairs, 2, CLOG_TIME_MPI_TYPE, sync->best_gpofst, 2, CLOG_TIME_MPI_TYPE, sync->root, MPI_COMM_WORLD ); if ( sync->world_rank == sync->root ) FREE( gpofst_pairs ); } else { /* root == 0 */ PMPI_Send( best_gpofst, 2, CLOG_TIME_MPI_TYPE, next_world_rank, CLOG_SYNC_TIME_QUERY, MPI_COMM_WORLD ); PMPI_Recv( best_gpofst, 2, CLOG_TIME_MPI_TYPE, prev_world_rank, CLOG_SYNC_TIME_QUERY, MPI_COMM_WORLD, &status ); if ( sync->world_rank == 0 ) { best_gpofst[0] = 0.0; best_gpofst[1] = 0.0; } PMPI_Scan( best_gpofst, sync->best_gpofst, 2, CLOG_TIME_MPI_TYPE, MPI_SUM, MPI_COMM_WORLD ); } return sync->best_gpofst[1];}/*@ CLOG_Sync_run - synchronize clocks with selected algorithm through MPE_SYNC_ALGORITHMInout Parameters:+ sync - CLOG_Sync_t contains local best_gpofst[2] to be filled inReturn value: local time offset after synchronization@*/CLOG_Time_t CLOG_Sync_run( CLOG_Sync_t *sync ){ switch ( sync->algorithm_ID ) { case CLOG_SYNC_AGRM_DEFAULT: if ( sync->world_size > 16 ) return CLOG_Sync_run_bitree( sync ); else return CLOG_Sync_run_seq( sync ); case CLOG_SYNC_AGRM_SEQ: return CLOG_Sync_run_seq( sync ); case CLOG_SYNC_AGRM_BITREE: return CLOG_Sync_run_bitree( sync ); case CLOG_SYNC_AGRM_ALTNGBR: return CLOG_Sync_run_altngbr( sync ); default: if ( sync->world_rank == 0 ) { fprintf( stderr, __FILE__":CLOG_Sync_run() - \n" "Unknown MPE_SYNC_ALGORITHM ID = %d." "Assume default synchronization mechanism.\n", sync->algorithm_ID ); fflush( stderr ); } if ( sync->world_size > 16 ) return CLOG_Sync_run_bitree( sync ); else return CLOG_Sync_run_seq( sync ); }}char *CLOG_Sync_print_type( const CLOG_Sync_t *sync ){ switch ( sync->algorithm_ID ) { case CLOG_SYNC_AGRM_DEFAULT: return "Default"; case CLOG_SYNC_AGRM_SEQ: return "Seq"; case CLOG_SYNC_AGRM_BITREE: return "BiTree"; case CLOG_SYNC_AGRM_ALTNGBR: return "AltNgbr"; default: return "Unknown(assume Default)"; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -