00001
00002
00003
00004
00013 #ifdef __TREE_SKELETONS_H__
00014 #ifndef __TREE_SKELETONS_TPP__
00015 #define __TREE_SKELETONS_TPP__
00016
00017 #include <iostream>
00018 #include <fstream>
00019 #include <cstdlib>
00020 #include <assert.h>
00021
00022 #include <mpi.h>
00023
00024 enum {
00025 TAG_REDUCE,
00026 TAG_UACC,
00027 TAG_DACC,
00028 TAG_DISTRIBUTE,
00029 TAG_DISTRIBUTE2,
00030 TAG_GATHER,
00031 TAG_SHIFTP,
00032 TAG_SHIFTL,
00033 TAG_SHIFTR,
00034 };
00035
00036
00037 template< typename K1, typename K2 >
00038 inline dist_tree< typename K1::result_type > *
00039 tree_skeletons::map( const K1 &k1,
00040 const K2 &k2,
00041 dist_tree< typename K1::argument_type > *t )
00042 {
00043 return map_adapter<
00044 typename K1::result_type,
00045 typename K1::argument_type,
00046 K1, K2 >( k1, k2, t );
00047 }
00048
00049
00050 template< typename C, typename A, typename K1, typename K2 >
00051 inline dist_tree< C >*
00052 tree_skeletons::map_adapter( const K1 &k1,
00053 const K2 &k2,
00054 dist_tree< A > *t )
00055 {
00056 dist_tree< C >* ret_tree = new dist_tree< C >( t );
00057 if ( !t->local_root ) return ret_tree;
00058
00059 ret_tree->local_root = map_rec< C, A, K1, K2 >( k1, k2, t->local_root );
00060 return ret_tree;
00061 }
00062
00063
00064 template< typename C, typename A, typename K1, typename K2 >
00065 node< C >*
00066 tree_skeletons::map_rec( const K1 &k1,
00067 const K2 &k2,
00068 node< A >* root )
00069 {
00070 node< C >* ret;
00071 if ( !root->isLeaf( ) ) {
00072
00073 ret = new node< C >( k2( root->value ), node< C >::NORMAL );
00074 ret->left = map_rec< C, A, K1, K2 >( k1, k2, root->left );
00075 ret->left->parent = ret;
00076
00077 ret->right = map_rec< C, A, K1, K2 >( k1, k2, root->right );
00078 ret->right->parent = ret;
00079
00080 } else if ( root->nodetype == node< A >::NORMAL ) {
00081
00082 ret = new node< C >( k1( root->value ), node< C >::NORMAL );
00083
00084 } else {
00085
00086 ret = new node< C >( k2( root->value ), node< C >::CUTNODE );
00087 }
00088 return ret;
00089 }
00090
00091
00092 template< typename K1, typename K2 >
00093 inline dist_tree< typename K1::result_type > *
00094 tree_skeletons::zipwith( const K1 &k1,
00095 const K2 &k2,
00096 const dist_tree< typename K1::first_argument_type >* at,
00097 const dist_tree< typename K1::second_argument_type >* bt )
00098 {
00099 return zipwith_adapter<
00100 typename K1::result_type,
00101 typename K1::first_argument_type,
00102 typename K1::second_argument_type,
00103 K1, K2 >( k1, k2, at, bt );
00104 }
00105
00106
00107 template< typename E, typename A, typename C, typename K1, typename K2 >
00108 dist_tree< E >*
00109 tree_skeletons::zipwith_adapter( const K1 &k1,
00110 const K2 &k2,
00111 const dist_tree< A >* at,
00112 const dist_tree< C >* bt )
00113 {
00114 dist_tree< E >* ret_tree = new dist_tree< E >( at );
00115 if ( !at->local_root ) return ret_tree;
00116
00117 ret_tree->local_root
00118 = zipwith_rec< E, A, C, K1, K2 >( k1, k2, at->local_root, bt->local_root );
00119 return ret_tree;
00120 }
00121
00122
00123 template< typename E, typename A, typename C, typename K1, typename K2 >
00124 node< E >*
00125 tree_skeletons::zipwith_rec( const K1 &k1,
00126 const K2 &k2,
00127 const node< A >* root_a,
00128 const node< C >* root_b )
00129 {
00130 node< E >* ret_node;
00131 if ( !root_a->isLeaf( ) ) {
00132
00133 ret_node = new node< E >( k2( root_a->value, root_b->value ),
00134 node< E >::NORMAL );
00135 ret_node->left
00136 = zipwith_rec< E, A, C, K1, K2 >( k1, k2, root_a->left, root_b->left );
00137 ret_node->left->parent = ret_node;
00138 ret_node->right
00139 = zipwith_rec< E, A, C, K1, K2 >( k1, k2, root_a->right, root_b->right );
00140 ret_node->right->parent = ret_node;
00141
00142 } else if ( root_a->nodetype == node< A >::NORMAL ) {
00143
00144 ret_node = new node< E >( k1( root_a->value, root_b->value ),
00145 node< E >::NORMAL );
00146 } else {
00147
00148 ret_node = new node< E >( k2( root_a->value, root_b->value ),
00149 node< E >::CUTNODE );
00150 }
00151 return ret_node;
00152 }
00153
00154
00155 template< typename K1, typename K2,
00156 typename PSI, typename PHIL, typename PHIR, typename GG >
00157 inline typename K1::result_type
00158 tree_skeletons::reduce( const K1 &k1,
00159 const K2 &k2,
00160 const PSI &psi,
00161 const PHIL &phiL,
00162 const PHIR &phiR,
00163 const GG &G,
00164 const dist_tree< typename K1::argument_type >* t )
00165 {
00166 return reduce_adapter<
00167 typename K1::result_type,
00168 typename PSI::result_type,
00169 typename K1::argument_type,
00170 K1, K2, PSI, PHIL, PHIR, GG >( k1, k2, psi, phiL, phiR, G, t );
00171 }
00172
00173
00174 template< typename C, typename D, typename A, typename K1, typename K2,
00175 typename PSI, typename PHIL, typename PHIR, typename GG >
00176 C
00177 tree_skeletons::reduce_adapter( const K1 &k1,
00178 const K2 &k2,
00179 const PSI &psi,
00180 const PHIL &phiL,
00181 const PHIR &phiR,
00182 const GG &G,
00183 const dist_tree< A >* t )
00184 {
00185
00186 if ( !t->local_root ) { return static_cast< C >( false ); }
00187
00188
00189 reduce_result_t< C, D > local_result
00190 = reduce_local_rec< C, D, A, K1, K2, PSI, PHIL, PHIR >
00191 ( k1, k2, psi, phiL, phiR, t->local_root );
00192
00193
00194 return reduce_global< C, D, A, GG >( G, local_result, t );
00195 }
00196
00197
00198 template< typename C, typename D, typename A, typename K1, typename K2,
00199 typename PSI, typename PHIL, typename PHIR >
00200 tree_skeletons::reduce_result_t< C, D >
00201 tree_skeletons::reduce_local_rec( const K1 &k1,
00202 const K2 &k2,
00203 const PSI &psi,
00204 const PHIL &phiL,
00205 const PHIR &phiR,
00206 const node< A >* root )
00207 {
00208 reduce_result_t< C, D > ret;
00209 if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
00210
00211 ret.resulttype = reduce_result_t< C, D >::TYPEC;
00212 ret.valC = k1( root->value );
00213 } else if ( root->isLeaf( ) && root->nodetype == node< A >::CUTNODE ) {
00214
00215 ret.resulttype = reduce_result_t< C, D >::TYPED;
00216 ret.valD = psi( root->value );
00217 } else {
00218
00219 reduce_result_t< C, D > retl
00220 = reduce_local_rec< C, D, A, K1, K2, PSI, PHIL, PHIR >
00221 ( k1, k2, psi, phiL, phiR, root->left );
00222 reduce_result_t< C, D > retr
00223 = reduce_local_rec< C, D, A, K1, K2, PSI, PHIL, PHIR >
00224 ( k1, k2, psi, phiL, phiR, root->right );
00225
00226 if ( retl.resulttype == reduce_result_t< C, D >::TYPEC &&
00227 retr.resulttype == reduce_result_t< C, D >::TYPEC ) {
00228
00229 ret.resulttype = reduce_result_t< C, D >::TYPEC;
00230 ret.valC = k2( root->value, retl.valC, retr.valC );
00231
00232 } else if ( retl.resulttype == reduce_result_t< C, D >::TYPED &&
00233 retr.resulttype == reduce_result_t< C, D >::TYPEC ) {
00234
00235 ret.resulttype = reduce_result_t< C, D >::TYPED;
00236 ret.valD = phiR( psi( root->value ), retr.valC, retl.valD );
00237
00238 } else if ( retl.resulttype == reduce_result_t< C, D >::TYPEC &&
00239 retr.resulttype == reduce_result_t< C, D >::TYPED ) {
00240
00241 ret.resulttype = reduce_result_t< C, D >::TYPED;
00242 ret.valD = phiL( psi( root->value ), retl.valC, retr.valD );
00243
00244 } else {
00245
00246 assert( false );
00247 }
00248 }
00249 return ret;
00250 }
00251
00252
00253 template< typename C, typename D, typename A, typename GG >
00254 C
00255 tree_skeletons::reduce_global( const GG &G,
00256 const tree_skeletons::reduce_result_t< C, D > &local_result,
00257 const dist_tree< A > *t )
00258 {
00259 C result;
00260
00261 if ( t->global_node->isLeaf( ) ) {
00262 result = local_result.valC;
00263 } else {
00264 C resultl, resultr;
00265
00266 MPI_Request req1, req2;
00267 MPI_Irecv( &resultl, sizeof( C ), MPI_BYTE,
00268 t->proc_leftchild, TAG_REDUCE, MPI_COMM_WORLD, &req1 );
00269 MPI_Irecv( &resultr, sizeof( C ), MPI_BYTE,
00270 t->proc_rightchild, TAG_REDUCE, MPI_COMM_WORLD, &req2 );
00271 MPI_Wait( &req1, MPI_STATUS_IGNORE );
00272 MPI_Wait( &req2, MPI_STATUS_IGNORE );
00273
00274 result = G( local_result.valD, resultl, resultr );
00275 }
00276
00277 if ( skeleton::rank != 0 ) {
00278 MPI_Request req;
00279 MPI_Isend( &result, sizeof( C ), MPI_BYTE,
00280 t->proc_parent, TAG_REDUCE, MPI_COMM_WORLD, &req );
00281 MPI_Wait( &req, MPI_STATUS_IGNORE );
00282 }
00283
00284 return result;
00285 }
00286
00287
00288 template< typename K1, typename K2,
00289 typename PSI, typename PHIL, typename PHIR, typename GG >
00290 inline dist_tree< typename K1::result_type > *
00291 tree_skeletons::uAcc( const K1 &k1,
00292 const K2 &k2,
00293 const PSI &psi,
00294 const PHIL &phiL,
00295 const PHIR &phiR,
00296 const GG &G,
00297 const dist_tree< typename K1::argument_type > *t )
00298 {
00299 return uAcc_adapter<
00300 typename K1::result_type,
00301 typename PSI::result_type,
00302 typename K1::argument_type,
00303 K1, K2, PSI, PHIL, PHIR, GG >( k1, k2, psi, phiL, phiR, G, t );
00304 }
00305
00306
00307 template< typename C, typename D, typename A, typename K1, typename K2,
00308 typename PSI, typename PHIL, typename PHIR, typename GG >
00309 dist_tree< C >*
00310 tree_skeletons::uAcc_adapter( const K1 &k1,
00311 const K2 &k2,
00312 const PSI &psi,
00313 const PHIL &phiL,
00314 const PHIR &phiR,
00315 const GG &G,
00316 const dist_tree< A > *t )
00317 {
00318 dist_tree< C >* ret_tree = new dist_tree< C >( t );
00319 if ( !t->local_root ) return ret_tree;
00320
00321
00322 tree_skeletons::reduce_result_t< C, D > local_result
00323 = reduce_local_rec< C, D, A, K1, K2, PSI, PHIL, PHIR >
00324 ( k1, k2, psi, phiL, phiR, t->local_root );
00325
00326
00327 C vall, valr;
00328 uAcc_global_uAcc< C, D, A, GG >( G, local_result, &vall, &valr, t );
00329
00330
00331 ret_tree->local_root
00332 = uAcc_local_uAcc_rec< C, D, A, K1, K2 >
00333 ( k1, k2, vall, valr, t->local_root );
00334
00335 return ret_tree;
00336 }
00337
00338
00339 template< typename C, typename D, typename A, typename GG >
00340 void
00341 tree_skeletons::uAcc_global_uAcc( const GG &G,
00342 const tree_skeletons::reduce_result_t< C, D > &local_result,
00343 C *vall,
00344 C *valr,
00345 const dist_tree< A > *t )
00346 {
00347 C result;
00348
00349 if ( t->global_node->isLeaf( ) ) {
00350 result = local_result.valC;
00351 } else {
00352
00353 MPI_Request req1, req2;
00354 MPI_Irecv( vall, sizeof( C ), MPI_BYTE,
00355 t->proc_leftchild, TAG_UACC, MPI_COMM_WORLD, &req1 );
00356 MPI_Irecv( valr, sizeof( C ), MPI_BYTE,
00357 t->proc_rightchild, TAG_UACC, MPI_COMM_WORLD, &req2 );
00358 MPI_Wait( &req1, MPI_STATUS_IGNORE );
00359 MPI_Wait( &req2, MPI_STATUS_IGNORE );
00360
00361 result = G( local_result.valD, *vall, *valr );
00362 }
00363
00364 if ( skeleton::rank != 0 ) {
00365 MPI_Request req;
00366 MPI_Isend( &result, sizeof( C ), MPI_BYTE,
00367 t->proc_parent, TAG_UACC, MPI_COMM_WORLD, &req );
00368 MPI_Wait( &req, MPI_STATUS_IGNORE );
00369 }
00370 }
00371
00372
00373 template< typename C, typename D, typename A, typename K1, typename K2 >
00374 node< C >*
00375 tree_skeletons::uAcc_local_uAcc_rec( const K1 &k1,
00376 const K2 &k2,
00377 const C& left_result,
00378 const C& right_result,
00379 const node< A > *root )
00380 {
00381 node< C > *ret_node;
00382
00383 if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
00384
00385 ret_node = new node< C >( k1( root->value ), node< C >::NORMAL );
00386 } else if ( root->nodetype == node< A >::CUTNODE ) {
00387
00388 ret_node = new node< C >( k2( root->value, left_result, right_result ),
00389 node< C >::CUTNODE );
00390 } else {
00391
00392 node< C >* left_node
00393 = uAcc_local_uAcc_rec< C, D, A, K1, K2 >
00394 ( k1, k2, left_result, right_result, root->left );
00395 node< C >* right_node
00396 = uAcc_local_uAcc_rec< C, D, A, K1, K2 >
00397 ( k1, k2, left_result, right_result, root->right );
00398
00399 ret_node
00400 = new node< C >( k2( root->value, left_node->value, right_node->value ),
00401 node< C >::NORMAL );
00402 ret_node->left = left_node; ret_node->left->parent = ret_node;
00403 ret_node->right = right_node; ret_node->right->parent = ret_node;
00404 }
00405
00406 return ret_node;
00407 }
00408
00409
00410 template< typename OPLUS, typename GL, typename GR >
00411 inline dist_tree< typename OPLUS::result_type > *
00412 tree_skeletons::dAcc( const OPLUS &oplus,
00413 const typename OPLUS::result_type &e_oplus,
00414 const GL &gl,
00415 const GR &gr,
00416 const typename OPLUS::result_type &c,
00417 const dist_tree< typename GL::argument_type >* t )
00418 {
00419 return dAcc_adapter<
00420 typename OPLUS::result_type,
00421 typename GL::argument_type,
00422 OPLUS, GL, GR >( oplus, e_oplus, gl, gr, c, t );
00423 }
00424
00425
00426 template< typename C, typename A, typename OPLUS, typename GL, typename GR >
00427 dist_tree< C >*
00428 tree_skeletons::dAcc_adapter( const OPLUS &oplus,
00429 const C &e_oplus,
00430 const GL &gl,
00431 const GR &gr,
00432 const C &c,
00433 const dist_tree< A >* t )
00434 {
00435 dist_tree< C >* ret_tree = new dist_tree< C >( t );
00436 if ( !t->local_root ) return ret_tree;
00437
00438
00439 C c_to_left = e_oplus, c_to_right = e_oplus;
00440 dAcc_local_path_rec< C, A, OPLUS, GL, GR >
00441 ( oplus, gl, gr, t->local_root, &c_to_left, &c_to_right );
00442
00443
00444 C c_from_parent
00445 = dAcc_global_dAcc< C, A, OPLUS >( oplus, c, c_to_left, c_to_right, t );
00446
00447
00448 ret_tree->local_root
00449 = dAcc_local_dAcc_rec< C, A, OPLUS, GL, GR >
00450 ( oplus, gl, gr, c_from_parent, t->local_root );
00451
00452 return ret_tree;
00453 }
00454
00455
00456 template< typename C, typename A, typename OPLUS, typename GL, typename GR >
00457 bool
00458 tree_skeletons::dAcc_local_path_rec( const OPLUS &oplus,
00459 const GL &gl,
00460 const GR &gr,
00461 const node< A >* root,
00462 C *c_to_left,
00463 C *c_to_right )
00464 {
00465 if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
00466
00467 return false;
00468 } else if ( root->isLeaf( ) && root->nodetype == node< A >::CUTNODE ) {
00469
00470 *c_to_left = gl( root->value );
00471 *c_to_right = gr( root->value );
00472 return true;
00473 } else {
00474
00475 if ( dAcc_local_path_rec( oplus, gl, gr, root->left,
00476 c_to_left, c_to_right ) ) {
00477 *c_to_left = oplus( gl( root->value ), *c_to_left );
00478 *c_to_right = oplus( gl( root->value ), *c_to_right );
00479 return true;
00480 }
00481 if ( dAcc_local_path_rec( oplus, gl, gr, root->right,
00482 c_to_left, c_to_right ) ) {
00483 *c_to_left = oplus( gr( root->value ), *c_to_left );
00484 *c_to_right = oplus( gr( root->value ), *c_to_right );
00485 return true;
00486 }
00487 return false;
00488 }
00489 }
00490
00491
00492 template< typename C, typename A, typename OPLUS >
00493 C
00494 tree_skeletons::dAcc_global_dAcc( const OPLUS &oplus,
00495 const C &c,
00496 const C &c_to_left,
00497 const C &c_to_right,
00498 const dist_tree< A >* t )
00499 {
00500 C c_from_parent;
00501 if ( skeleton::rank == 0 ) {
00502 c_from_parent = c;
00503 } else {
00504 MPI_Request req;
00505 MPI_Irecv( &c_from_parent, sizeof( C ), MPI_BYTE,
00506 t->proc_parent, TAG_DACC, MPI_COMM_WORLD, &req );
00507 MPI_Wait( &req, MPI_STATUS_IGNORE );
00508 }
00509
00510 if ( t->global_node->isLeaf( ) ) {
00511 } else {
00512 C sent_c_to_left = oplus( c_from_parent, c_to_left );
00513 C sent_c_to_right = oplus( c_from_parent, c_to_right );
00514
00515 MPI_Request req1, req2;
00516 MPI_Isend( &sent_c_to_left, sizeof( C ), MPI_BYTE,
00517 t->proc_leftchild, TAG_DACC, MPI_COMM_WORLD, &req1 );
00518 MPI_Isend( &sent_c_to_right, sizeof( C ), MPI_BYTE,
00519 t->proc_rightchild, TAG_DACC, MPI_COMM_WORLD, &req2 );
00520 MPI_Wait( &req1, MPI_STATUS_IGNORE );
00521 MPI_Wait( &req2, MPI_STATUS_IGNORE );
00522
00523 }
00524
00525 return c_from_parent;
00526 }
00527
00528
00529 template< typename C, typename A, typename OPLUS, typename GL, typename GR >
00530 node< C >*
00531 tree_skeletons::dAcc_local_dAcc_rec( const OPLUS &oplus,
00532 const GL &gl,
00533 const GR &gr,
00534 const C &c,
00535 const node< A >* root )
00536 {
00537 node< C >* ret_node
00538 = new node< C >( c, ( root->nodetype == node< A >::NORMAL ) ? node< C >::NORMAL : node< C >::CUTNODE );
00539
00540 if ( !root->isLeaf( ) ) {
00541 ret_node->left = dAcc_local_dAcc_rec( oplus, gl, gr,
00542 oplus( c, gl( root->value ) ),
00543 root->left );
00544 ret_node->left->parent = ret_node;
00545 ret_node->right = dAcc_local_dAcc_rec( oplus, gl, gr,
00546 oplus( c, gr( root->value ) ),
00547 root->right );
00548 ret_node->right->parent = ret_node;
00549 }
00550
00551 return ret_node;
00552 }
00553
00554
00555 template< typename A >
00556 dist_tree< A >*
00557 tree_skeletons::distribute2( const node< A >* s_tree )
00558 {
00559 dist_tree< A >* d_tree = new dist_tree< A >( );
00560
00561 if ( skeleton::rank == 0 ) {
00562
00563
00564
00565 node< tree_skeletons::size_and_critical< A > >* global_root;
00566 int np;
00567 int size;
00568
00569 if ( !compute_size_and_get_global_tree( s_tree, skeleton::procs, &global_root, &np, &size ) ) {
00570 std::exit( 1 );
00571 }
00572
00573
00574 MPI_Bcast( &np, 1, MPI_INT, 0, MPI_COMM_WORLD );
00575
00576
00577 int *localsizes = new int[ np ];
00578 const node< A >** subroots = new const node< A >*[ np ];
00579 const node< A >** subcrits = new const node< A >*[ np ];
00580 {
00581 int *flags = new int[ np ];
00582 serialize_global_structure( s_tree, global_root, size,
00583 flags, localsizes, subroots, subcrits );
00584
00585 MPI_Bcast( flags, np, MPI_INT, 0, MPI_COMM_WORLD );
00586 MPI_Bcast( localsizes, np, MPI_INT, 0, MPI_COMM_WORLD );
00587
00588 d_tree->read_from_file_create_global_tree( flags, localsizes );
00589
00590 delete [] flags;
00591 }
00592
00593
00594 int max_size = 0;
00595 for ( int p = 0; p < np; p++ ) {
00596 if ( max_size < localsizes[ p ] ) max_size = localsizes[ p ];
00597 }
00598
00599 int *flags = new int[ max_size ];
00600 A *values = new A[ max_size ];
00601
00602
00603 for ( int p = 1; p < np; p++ ) {
00604 get_local_tree( subroots[ p ], subcrits[ p ], flags, values );
00605
00606 MPI_Request req1, req2;
00607 MPI_Isend( flags, localsizes[ p ], MPI_INT,
00608 p, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req1 );
00609 MPI_Isend( values, localsizes[ p ] * sizeof( A ), MPI_BYTE,
00610 p, TAG_DISTRIBUTE2, MPI_COMM_WORLD, &req2 );
00611 MPI_Wait( &req1, MPI_STATUS_IGNORE );
00612 MPI_Wait( &req2, MPI_STATUS_IGNORE );
00613 }
00614
00615
00616 {
00617 get_local_tree( subroots[ 0 ], subcrits[ 0 ], flags, values );
00618 d_tree->read_from_file_create_subtree( flags, values );
00619 }
00620
00621 delete [] values;
00622 delete [] flags;
00623 }
00624 else {
00625
00626
00627 int np;
00628 MPI_Bcast( &np, 1, MPI_INT, 0, MPI_COMM_WORLD );
00629
00630
00631 {
00632 int *localsizes = new int[ np ];
00633 int *flags = new int[ np ];
00634
00635 MPI_Bcast( flags, np, MPI_INT, 0, MPI_COMM_WORLD );
00636 MPI_Bcast( localsizes, np, MPI_INT, 0, MPI_COMM_WORLD );
00637
00638 d_tree->read_from_file_create_global_tree( flags, localsizes );
00639
00640 delete[] flags;
00641 delete[] localsizes;
00642 }
00643
00644
00645 if ( skeleton::rank < np ) {
00646 const int localsize = d_tree->global_node->value;
00647 int *flags = new int[ localsize ];
00648 A *values = new A[ localsize ];
00649
00650 MPI_Request req1, req2;
00651 MPI_Irecv( flags, localsize, MPI_INT,
00652 0, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req1 );
00653 MPI_Irecv( values, localsize * sizeof( A ), MPI_BYTE,
00654 0, TAG_DISTRIBUTE2, MPI_COMM_WORLD, &req2 );
00655 MPI_Wait( &req1, MPI_STATUS_IGNORE );
00656 MPI_Wait( &req2, MPI_STATUS_IGNORE );
00657
00658 d_tree->read_from_file_create_subtree( flags, values );
00659
00660 delete[] values;
00661 delete[] flags;
00662 }
00663 }
00664
00665 return d_tree;
00666 }
00667
00668 template< typename A >
00669 int temp_get_size_rec( const node< A >* tree )
00670 {
00671 if ( tree == NULL ) return 0;
00672
00673 int size_left, size_right;
00674 size_left = temp_get_size_rec( tree->left );
00675 size_right = temp_get_size_rec( tree->right );
00676
00677 return 1 + size_left + size_right;
00678 }
00679
00680 template< typename A >
00681 bool
00682 tree_skeletons::compute_size_and_get_global_tree( const node< A >* tree,
00683 int nprocs,
00684 node< size_and_critical< A > >** global_root,
00685 int *np,
00686 int *size )
00687 {
00688
00689 *size = tree_util::get_size_rec( tree );
00690 int m = 2 * *size / ( nprocs / 2 + 1 );
00691
00692
00693 node< size_and_critical< A > >* global_tree;
00694 int s;
00695 get_global_tree_rec( &global_tree, &s, tree, m );
00696
00697 *np = temp_get_size_rec( global_tree ) * 2 + 1;
00698 assert( *np <= nprocs );
00699
00700 *global_root = global_tree;
00701
00702 return true;
00703 }
00704
00705 template< typename A >
00706 void
00707 tree_skeletons::get_global_tree_rec( node< size_and_critical< A > >** global_tree,
00708 int *size_root,
00709 const node< A >* tree,
00710 int m )
00711 {
00712 if ( tree->isLeaf( ) ) {
00713 *global_tree = NULL;
00714 *size_root = 1;
00715 return;
00716 }
00717
00718 int size, size_left, size_right;
00719 node< size_and_critical< A > > *global_root, *global_left, *global_right;
00720
00721 get_global_tree_rec( &global_left, &size_left, tree->left, m );
00722 get_global_tree_rec( &global_right, &size_right, tree->right, m );
00723
00724 size = 1 + size_left + size_right;
00725 if ( ( tree_util::ceil_divided_by_m( size, m )
00726 > tree_util::ceil_divided_by_m( size_left, m ) ) &&
00727 ( tree_util::ceil_divided_by_m( size, m )
00728 > tree_util::ceil_divided_by_m( size_right, m ) ) ) {
00729 global_root = new node< size_and_critical< A > >( );
00730 global_root->value.critical_node = tree;
00731 global_root->value.left_size = size_left;
00732 global_root->value.right_size = size_right;
00733
00734 global_root->left = global_left;
00735 global_root->right = global_right;
00736 if ( global_root->left ) global_root->left ->parent = global_root;
00737 if ( global_root->right ) global_root->right->parent = global_root;
00738
00739 *global_tree = global_root;
00740 *size_root = size;
00741 } else {
00742 if ( global_left ) {
00743 *global_tree = global_left;
00744 } else {
00745 *global_tree = global_right;
00746 }
00747 *size_root = size;
00748
00749 }
00750 }
00751
00752 template< typename A >
00753 void
00754 tree_skeletons::serialize_global_structure( const node< A >* tree,
00755 const node< size_and_critical< A > >* global_root,
00756 int size,
00757 int *flags,
00758 int *localsizes,
00759 const node< A >** subroots,
00760 const node< A >** subcrits )
00761 {
00762 int index = 0;
00763 serialize_global_structure_rec( tree, global_root, size,
00764 flags, localsizes, subroots, subcrits,
00765 &index );
00766 }
00767
00768 template< typename A >
00769 void
00770 tree_skeletons::serialize_global_structure_rec( const node< A >* tree,
00771 const node< size_and_critical< A > >* global_root,
00772 int size,
00773 int *flags,
00774 int *localsizes,
00775 const node< A >** subroots,
00776 const node< A >** subcrits,
00777 int *index )
00778 {
00779 int cur_index = (*index)++;
00780 flags[ cur_index ] = ( global_root ? node< size_and_critical< A > >::SER_NODE :
00781 node< size_and_critical< A > >::SER_LEAF );
00782 localsizes[ cur_index ] = ( global_root ?
00783 size - global_root->value.left_size - global_root->value.right_size :
00784 size );
00785 subroots[ cur_index ] = tree;
00786 subcrits[ cur_index ] = ( global_root ? global_root->value.critical_node : NULL );
00787
00788 if ( global_root ) {
00789 serialize_global_structure_rec( global_root->value.critical_node->left,
00790 global_root->left,
00791 global_root->value.left_size,
00792 flags,
00793 localsizes,
00794 subroots,
00795 subcrits,
00796 index );
00797 serialize_global_structure_rec( global_root->value.critical_node->right,
00798 global_root->right,
00799 global_root->value.right_size,
00800 flags,
00801 localsizes,
00802 subroots,
00803 subcrits,
00804 index );
00805 }
00806 }
00807
00808 template< typename A >
00809 void
00810 tree_skeletons::get_local_tree( const node< A >* root,
00811 const node< A >* crit_node,
00812 int *flags,
00813 A *values )
00814 {
00815 int index = 0;
00816 get_local_tree_rec( root, crit_node, flags, values, &index );
00817 }
00818
00819 template< typename A >
00820 void
00821 tree_skeletons::get_local_tree_rec( const node< A >* root,
00822 const node< A >* crit_node,
00823 int *flags,
00824 A *values,
00825 int *index )
00826 {
00827 int cur_index = (*index)++;
00828
00829 values[ cur_index ] = root->value;
00830
00831 if ( root == crit_node ) {
00832 flags[ cur_index ] = node< A >::SER_CUTNODE;
00833 } else if ( root->isLeaf( ) ) {
00834 flags[ cur_index ] = node< A >::SER_LEAF;
00835 } else {
00836 flags[ cur_index ] = node< A >::SER_NODE;
00837
00838 get_local_tree_rec( root->left, crit_node, flags, values, index );
00839 get_local_tree_rec( root->right, crit_node, flags, values, index );
00840 }
00841 }
00842
00843
00844 template< typename A >
00845 dist_tree< A >*
00846 tree_skeletons::distribute( const node< A >* s_tree )
00847 {
00848 dist_tree< A >* d_tree = new dist_tree< A >( );
00849
00850 if ( skeleton::rank == 0 ) {
00851
00852 assert( tree_util::check_perfect_binary_tree( s_tree ) );
00853
00854 node< tree_util::IntermediateVal< A > > *size_crit_tree;
00855 int np;
00856
00857 if ( !tree_util::compute_size_and_mark_critical( s_tree, skeleton::procs, &size_crit_tree, &np ) ) {
00858 std::exit( 1 );
00859 }
00860
00861
00862 MPI_Bcast( &np, 1, MPI_INT, 0, MPI_COMM_WORLD );
00863
00864
00865 int *localsizes = new int[ np ];
00866 node< tree_util::IntermediateVal< A > > **subroots
00867 = new node< tree_util::IntermediateVal< A > >*[ np ];
00868 {
00869 int *flags = new int[ np ];
00870 tree_util::get_global_tree( size_crit_tree, flags, localsizes, subroots );
00871
00872 MPI_Bcast( flags, np, MPI_INT, 0, MPI_COMM_WORLD );
00873 MPI_Bcast( localsizes, np, MPI_INT, 0, MPI_COMM_WORLD );
00874
00875 d_tree->read_from_file_create_global_tree( flags, localsizes );
00876 delete [] flags;
00877 }
00878
00879
00880 {
00881 int *flags = new int[ localsizes[ 0 ] ];
00882 A *values = new A[ localsizes[ 0 ] ];
00883
00884 tree_util::get_local_tree( subroots[ 0 ], flags, values );
00885 d_tree->read_from_file_create_subtree( flags, values );
00886
00887 delete[] values;
00888 delete[] flags;
00889 }
00890
00891
00892 for ( int p = 1; p < np; p++ ) {
00893 int *flags = new int[ localsizes[ p ] ];
00894 A *values = new A[ localsizes[ p ] ];
00895
00896 tree_util::get_local_tree( subroots[ p ], flags, values );
00897 MPI_Request req1, req2;
00898 MPI_Isend( flags, localsizes[ p ], MPI_INT,
00899 p, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req1 );
00900 MPI_Isend( values, localsizes[ p ] * sizeof( A ), MPI_BYTE,
00901 p, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req2 );
00902 MPI_Wait( &req1, MPI_STATUS_IGNORE );
00903 MPI_Wait( &req2, MPI_STATUS_IGNORE );
00904
00905 delete[] values;
00906 delete[] flags;
00907 }
00908 delete [] subroots;
00909 delete [] localsizes;
00910
00911 tree_util::free_all_tree( size_crit_tree );
00912
00913 } else {
00914
00915
00916
00917 int np;
00918 MPI_Bcast( &np, 1, MPI_INT, 0, MPI_COMM_WORLD );
00919
00920
00921 {
00922 int *localsizes = new int[ np ];
00923 int *flags = new int[ np ];
00924
00925 MPI_Bcast( flags, np, MPI_INT, 0, MPI_COMM_WORLD );
00926 MPI_Bcast( localsizes, np, MPI_INT, 0, MPI_COMM_WORLD );
00927
00928 d_tree->read_from_file_create_global_tree( flags, localsizes );
00929
00930 delete[] flags;
00931 delete[] localsizes;
00932 }
00933
00934
00935 if ( skeleton::rank < np ) {
00936 const int localsize = d_tree->global_node->value;
00937 int *flags = new int[ localsize ];
00938 A *values = new A[ localsize ];
00939
00940 MPI_Request req1, req2;
00941 MPI_Irecv( flags, localsize, MPI_INT,
00942 0, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req1 );
00943 MPI_Irecv( values, localsize * sizeof( A ), MPI_BYTE,
00944 0, TAG_DISTRIBUTE, MPI_COMM_WORLD, &req2 );
00945 MPI_Wait( &req1, MPI_STATUS_IGNORE );
00946 MPI_Wait( &req2, MPI_STATUS_IGNORE );
00947
00948 d_tree->read_from_file_create_subtree( flags, values );
00949
00950 delete[] values;
00951 delete[] flags;
00952 }
00953 }
00954
00955 return d_tree;
00956 }
00957
00958
00959 template< typename A >
00960 node< A >*
00961 tree_skeletons::gather( const dist_tree< A >* d_tree )
00962 {
00963 if ( skeleton::rank == 0 ) {
00964 node< A >* s_tree = gather_copy_tree( d_tree->local_root );
00965
00966 int proc = 1;
00967 gather_rec( s_tree, d_tree->global_root, &proc );
00968
00969 return s_tree;
00970 } else {
00971 if ( d_tree->global_node ) {
00972 int *flags = new int[ d_tree->global_node->value ];
00973 A *values = new A[ d_tree->global_node->value ];
00974 int *p_flags = flags;
00975 A *p_values = values;
00976
00977 tree_util::serialize_subtree( d_tree->local_root, &p_flags, &p_values );
00978
00979 MPI_Request req1, req2;
00980 MPI_Isend( flags, d_tree->global_node->value, MPI_INT,
00981 0, TAG_GATHER, MPI_COMM_WORLD, &req1 );
00982 MPI_Isend( values, d_tree->global_node->value*sizeof( A ), MPI_BYTE,
00983 0, TAG_GATHER, MPI_COMM_WORLD, &req2 );
00984 MPI_Wait( &req1, MPI_STATUS_IGNORE );
00985 MPI_Wait( &req2, MPI_STATUS_IGNORE );
00986
00987 delete [] values;
00988 delete [] flags;
00989 }
00990 return NULL;
00991 }
00992 }
00993
00994
00995 template< typename A >
00996 void
00997 tree_skeletons::gather_rec( node< A >* root,
00998 const node< int >* global_root,
00999 int *proc )
01000 {
01001 node< A >* cutnode = gather_find_cutnode( root );
01002 if ( cutnode ) {
01003 {
01004
01005 int curproc = (*proc)++;
01006 int size = global_root->left->value;
01007 int *flags = new int[ size ];
01008 A *values = new A[ size ];
01009
01010 MPI_Request req1, req2;
01011 MPI_Irecv( flags, size, MPI_INT,
01012 curproc, TAG_GATHER, MPI_COMM_WORLD, &req1 );
01013 MPI_Irecv( values, size * sizeof( A ), MPI_BYTE,
01014 curproc, TAG_GATHER, MPI_COMM_WORLD, &req2 );
01015 MPI_Wait( &req1, MPI_STATUS_IGNORE );
01016 MPI_Wait( &req2, MPI_STATUS_IGNORE );
01017
01018 cutnode->left = gather_create_subtree( flags, values );
01019 cutnode->left->parent = cutnode;
01020
01021 delete [] flags;
01022 delete [] values;
01023
01024 gather_rec( cutnode->left, global_root->left, proc );
01025 }
01026 {
01027
01028 int curproc = (*proc)++;
01029 int size = global_root->right->value;
01030 int *flags = new int[ size ];
01031 A *values = new A[ size ];
01032
01033 MPI_Request req1, req2;
01034 MPI_Irecv( flags, size, MPI_INT,
01035 curproc, TAG_GATHER, MPI_COMM_WORLD, &req1 );
01036 MPI_Irecv( values, size * sizeof( A ), MPI_BYTE,
01037 curproc, TAG_GATHER, MPI_COMM_WORLD, &req2 );
01038 MPI_Wait( &req1, MPI_STATUS_IGNORE );
01039 MPI_Wait( &req2, MPI_STATUS_IGNORE );
01040
01041 cutnode->right = gather_create_subtree( flags, values );
01042 cutnode->right->parent = cutnode;
01043
01044 delete [] flags;
01045 delete [] values;
01046
01047 gather_rec( cutnode->right, global_root->right, proc );
01048 }
01049 }
01050 }
01051
01052
01053 template< typename A >
01054 node< A >*
01055 tree_skeletons::gather_find_cutnode( node< A >* root )
01056 {
01057 if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
01058 return NULL;
01059 } else if ( root->isLeaf( ) && root->nodetype == node< A >::CUTNODE ) {
01060 return root;
01061 } else {
01062 node< A > *left, *right;
01063 left = gather_find_cutnode( root->left );
01064 if ( left ) return left;
01065 right = gather_find_cutnode( root->right );
01066 if ( right ) return right;
01067 return NULL;
01068 }
01069 }
01070
01071
01072 template< typename A >
01073 node< A >*
01074 tree_skeletons::gather_create_subtree( const int* flags,
01075 const A* values )
01076 {
01077 const int *pflags = flags;
01078 const A *pvalues = values;
01079 return dist_tree< A >::read_from_file_create_subtree_rec( &pflags, &pvalues );
01080 }
01081
01082
01083 template< typename A >
01084 node< A >*
01085 tree_skeletons::gather_copy_tree( const node< A >* root )
01086 {
01087 node< A >* ret_node = new node< A >( root->value, root->nodetype );
01088
01089 if ( root->isLeaf( ) ) {
01090 } else {
01091 ret_node->left = gather_copy_tree( root->left );
01092 ret_node->left->parent = ret_node;
01093 ret_node->right = gather_copy_tree( root->right );
01094 ret_node->right->parent = ret_node;
01095 }
01096
01097 return ret_node;
01098 }
01099
01100
01101 template< typename A >
01102 dist_tree< A >*
01103 tree_skeletons::shiftp( const A& rootval,
01104 const dist_tree< A >* tree )
01105 {
01106 dist_tree< A > *ret_tree = new dist_tree< A >( tree );
01107 if ( !tree->local_root ) return ret_tree;
01108
01109 A cut_node_val;
01110 ret_tree->local_root = shiftp_rec( tree->local_root, rootval, &cut_node_val );
01111
01112
01113 if ( !tree->global_node->isLeaf( ) ) {
01114 MPI_Request req1, req2;
01115 MPI_Isend( &cut_node_val, sizeof( A ), MPI_BYTE,
01116 tree->proc_leftchild, TAG_SHIFTP, MPI_COMM_WORLD, &req1 );
01117 MPI_Isend( &cut_node_val, sizeof( A ), MPI_BYTE,
01118 tree->proc_rightchild, TAG_SHIFTP, MPI_COMM_WORLD, &req2 );
01119 MPI_Wait( &req1, MPI_STATUS_IGNORE );
01120 MPI_Wait( &req2, MPI_STATUS_IGNORE );
01121 }
01122
01123
01124 A real_rootval;
01125 if ( skeleton::rank == 0 ) {
01126 real_rootval = rootval;
01127 } else {
01128 MPI_Request req;
01129 MPI_Irecv( &real_rootval, sizeof( A ), MPI_BYTE,
01130 tree->proc_parent, TAG_SHIFTP, MPI_COMM_WORLD, &req );
01131 MPI_Wait( &req, MPI_STATUS_IGNORE );
01132 }
01133 ret_tree->local_root->value = real_rootval;
01134 return ret_tree;
01135 }
01136
01137
01138 template< typename A >
01139 node< A > *
01140 tree_skeletons::shiftp_rec( const node< A >* root,
01141 const A& root_val,
01142 A *cut_node_val )
01143 {
01144 node< A > *ret_node = new node< A >( root_val, root->nodetype );
01145 if ( !root->isLeaf( ) ) {
01146 ret_node->left = shiftp_rec( root->left, root->value, cut_node_val );
01147 ret_node->right = shiftp_rec( root->right, root->value, cut_node_val );
01148 }
01149 if ( root->nodetype == node< A >::CUTNODE ) {
01150 *cut_node_val = root->value;
01151 }
01152 return ret_node;
01153 }
01154
01155
01156 template< typename A >
01157 dist_tree< A >*
01158 tree_skeletons::shiftl( const A& leafval,
01159 const dist_tree< A >* tree )
01160 {
01161 dist_tree< A > *ret_tree = new dist_tree< A >( tree );
01162 if ( !tree->local_root ) return ret_tree;
01163
01164
01165
01166 if ( tree->global_node->parent &&
01167 tree->global_node->parent->left == tree->global_node ) {
01168 MPI_Request req;
01169 MPI_Isend( &(tree->local_root->value), sizeof( A ), MPI_BYTE,
01170 tree->proc_parent, TAG_SHIFTL, MPI_COMM_WORLD, &req );
01171 MPI_Wait( &req, MPI_STATUS_IGNORE );
01172 }
01173
01174
01175 A left_child_root_val;
01176 if ( !tree->global_node->isLeaf( ) ) {
01177 MPI_Request req;
01178 MPI_Irecv( &left_child_root_val, sizeof( A ), MPI_BYTE,
01179 tree->proc_leftchild, TAG_SHIFTL, MPI_COMM_WORLD, &req );
01180 MPI_Wait( &req, MPI_STATUS_IGNORE );
01181 }
01182
01183 ret_tree->local_root = shiftl_rec( tree->local_root,
01184 leafval,
01185 left_child_root_val );
01186 return ret_tree;
01187 }
01188
01189
01190 template< typename A >
01191 node< A >*
01192 tree_skeletons::shiftl_rec( const node< A > *root,
01193 const A& leafval,
01194 const A& left_child_root_val )
01195 {
01196 node< A > *ret_node;
01197 if ( !root->isLeaf( ) ) {
01198
01199 ret_node = new node< A >( root->left->value, node< A >::NORMAL );
01200 ret_node->left = shiftl_rec( root->left, leafval, left_child_root_val );
01201 ret_node->right = shiftl_rec( root->right, leafval, left_child_root_val );
01202 } else if ( root->nodetype == node< A >::NORMAL ) {
01203
01204 ret_node = new node< A >( leafval, node< A >::NORMAL );
01205 } else {
01206
01207 ret_node = new node< A >( left_child_root_val, node< A >::CUTNODE );
01208 }
01209 return ret_node;
01210 }
01211
01212
01213 template< typename A >
01214 dist_tree< A >*
01215 tree_skeletons::shiftr( const A& leafval,
01216 const dist_tree< A >* tree )
01217 {
01218 dist_tree< A > *ret_tree = new dist_tree< A >( tree );
01219 if ( !tree->local_root ) return ret_tree;
01220
01221
01222
01223 if ( tree->global_node->parent &&
01224 tree->global_node->parent->right == tree->global_node ) {
01225 MPI_Request req;
01226 MPI_Isend( &(tree->local_root->value), sizeof( A ), MPI_BYTE,
01227 tree->proc_parent, TAG_SHIFTR, MPI_COMM_WORLD, &req );
01228 MPI_Wait( &req, MPI_STATUS_IGNORE );
01229 }
01230
01231
01232 A right_child_root_val;
01233 if ( !tree->global_node->isLeaf( ) ) {
01234 MPI_Request req;
01235 MPI_Irecv( &right_child_root_val, sizeof( A ), MPI_BYTE,
01236 tree->proc_rightchild, TAG_SHIFTR, MPI_COMM_WORLD, &req );
01237 MPI_Wait( &req, MPI_STATUS_IGNORE );
01238 }
01239
01240 ret_tree->local_root = shiftr_rec( tree->local_root,
01241 leafval,
01242 right_child_root_val );
01243 return ret_tree;
01244 }
01245
01246
01247 template< typename A >
01248 node< A >*
01249 tree_skeletons::shiftr_rec( const node< A > *root,
01250 const A& leafval,
01251 const A& right_child_root_val )
01252 {
01253 node< A > *ret_node;
01254 if ( !root->isLeaf( ) ) {
01255
01256 ret_node = new node< A >( root->right->value, node< A >::NORMAL );
01257 ret_node->left = shiftr_rec( root->left, leafval, right_child_root_val );
01258 ret_node->right = shiftr_rec( root->right, leafval, right_child_root_val );
01259 } else if ( root->nodetype == node< A >::NORMAL ) {
01260
01261 ret_node = new node< A >( leafval, node< A >::NORMAL );
01262 } else {
01263
01264 ret_node = new node< A >( right_child_root_val, node< A >::CUTNODE );
01265 }
01266 return ret_node;
01267 }
01268
01269
01270 #endif
01271 #endif