coll_tuned_topo.c
来自「MPI stands for the Message Passing Inter」· C语言 代码 · 共 544 行 · 第 1/2 页
C
544 行
/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2005 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */#include "ompi_config.h"#include "mpi.h"#include "ompi/constants.h"#include "ompi/datatype/datatype.h"#include "ompi/communicator/communicator.h"#include "ompi/mca/coll/coll.h"#include "ompi/mca/coll/base/coll_tags.h"#include "ompi/mca/pml/pml.h"#include "coll_tuned.h"#include "coll_tuned_topo.h"/* * Some static helpers. */static int pown( int fanout, int num ){ int j, p = 1; if( num < 0 ) return 0; if (1==num) return fanout; if (2==fanout) { return p<<num; } else { for( j = 0; j < num; j++ ) { p*= fanout; } } return p;}static int calculate_level( int fanout, int rank ){ int level, num; if( rank < 0 ) return -1; for( level = 0, num = 0; num <= rank; level++ ) { num += pown(fanout, level); } return level-1;}static int calculate_num_nodes_up_to_level( int fanout, int level ){ /* just use geometric progression formula for sum: a^0+a^1+...a^(n-1) = (a^n-1)/(a-1) */ return ((pown(fanout,level) - 1)/(fanout - 1));}/* * And now the building functions. */ompi_coll_tree_t*ompi_coll_tuned_topo_build_tree( int fanout, struct ompi_communicator_t* comm, int root ){ int rank, size; int schild, sparent; int level; /* location of my rank in the tree structure of size */ int delta; /* number of nodes on my level */ int slimit; /* total number of nodes on levels above me */ int shiftedrank; int i; ompi_coll_tree_t* tree; OPAL_OUTPUT((ompi_coll_tuned_stream, "coll:tuned:topo_build_tree Building fo %d rt %d", fanout, root)); if (fanout<1) { OPAL_OUTPUT((ompi_coll_tuned_stream, "coll:tuned:topo_build_tree invalid fanout %d", fanout)); return NULL; } if (fanout>MAXTREEFANOUT) { OPAL_OUTPUT((ompi_coll_tuned_stream,"coll:tuned:topo_build_tree invalid fanout %d bigger than max %d", fanout, MAXTREEFANOUT)); return NULL; } /* * Get size and rank of the process in this communicator */ size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); tree = (ompi_coll_tree_t*)malloc(sizeof(ompi_coll_tree_t)); if (!tree) { OPAL_OUTPUT((ompi_coll_tuned_stream,"coll:tuned:topo_build_tree PANIC::out of memory")); return NULL; } tree->tree_root = MPI_UNDEFINED; tree->tree_nextsize = MPI_UNDEFINED; /* * Set root */ tree->tree_root = root; /* * Initialize tree */ tree->tree_fanout = fanout; tree->tree_bmtree = 0; tree->tree_root = root; tree->tree_prev = -1; tree->tree_nextsize = 0; for( i = 0; i < fanout; i++ ) { tree->tree_next[i] = -1; } /* return if we have less than 2 processes */ if( size < 2 ) { return tree; } /* * Shift all ranks by root, so that the algorithm can be * designed as if root would be always 0 * shiftedrank should be used in calculating distances * and position in tree */ shiftedrank = rank - root; if( shiftedrank < 0 ) { shiftedrank += size; } /* calculate my level */ level = calculate_level( fanout, shiftedrank ); delta = pown( fanout, level ); /* find my children */ for( i = 0; i < fanout; i++ ) { schild = shiftedrank + delta * (i+1); if( schild < size ) { tree->tree_next[i] = (schild+root)%size; tree->tree_nextsize = tree->tree_nextsize + 1; } else { break; } } /* find my parent */ slimit = calculate_num_nodes_up_to_level( fanout, level ); sparent = shiftedrank; if( sparent < fanout ) { sparent = 0; } else { while( sparent >= slimit ) { sparent -= delta/fanout; } } tree->tree_prev = (sparent+root)%size; return tree;}/* * Constructs in-order binary tree which can be used for non-commutative reduce * operations. * Root of this tree is always rank (size-1) and fanout is 2. * Here are some of the examples of this tree: * size == 2 size = 4 size = 9 * 1 3 8 * / / \ / \ * 0 2 1 7 3 * / / \ / \ * 0 6 5 2 1 * / / * 4 0 */ompi_coll_tree_t*ompi_coll_tuned_topo_build_in_order_bintree( struct ompi_communicator_t* comm ){ int rank, size; int myrank, rightsize, delta; int parent, lchild, rchild; ompi_coll_tree_t* tree; /* * Get size and rank of the process in this communicator */ size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); tree = (ompi_coll_tree_t*)malloc(sizeof(ompi_coll_tree_t)); if (!tree) { OPAL_OUTPUT((ompi_coll_tuned_stream, "coll:tuned:topo_build_tree PANIC::out of memory")); return NULL; } tree->tree_root = MPI_UNDEFINED; tree->tree_nextsize = MPI_UNDEFINED; /* * Initialize tree */ tree->tree_fanout = 2; tree->tree_bmtree = 0; tree->tree_root = size - 1; tree->tree_prev = -1; tree->tree_nextsize = 0; tree->tree_next[0] = -1; tree->tree_next[1] = -1; OPAL_OUTPUT((ompi_coll_tuned_stream, "coll:tuned:topo_build_in_order_tree Building fo %d rt %d", tree->tree_fanout, tree->tree_root)); /* * Build the tree */ myrank = rank; parent = size - 1; delta = 0; while ( 1 ) { /* Compute the size of the right subtree */ rightsize = size >> 1; /* Determine the left and right child of this parent */ lchild = -1; rchild = -1; if (size - 1 > 0) { lchild = parent - 1; if (lchild > 0) { rchild = rightsize - 1; } } /* The following cases are possible: myrank can be - a parent, - belong to the left subtree, or - belong to the right subtee Each of the cases need to be handled differently. */ if (myrank == parent) { /* I am the parent: - compute real ranks of my children, and exit the loop. */ if (lchild >= 0) tree->tree_next[0] = lchild + delta; if (rchild >= 0) tree->tree_next[1] = rchild + delta; break; } if (myrank > rchild) { /* I belong to the left subtree: - If I am the left child, compute real rank of my parent - Iterate down through tree: compute new size, shift ranks down, and update delta. */ if (myrank == lchild) { tree->tree_prev = parent + delta; } size = size - rightsize - 1; delta = delta + rightsize; myrank = myrank - rightsize; parent = size - 1;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?