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 + -
显示快捷键?