coll_tuned_barrier.c

来自「MPI stands for the Message Passing Inter」· C语言 代码 · 共 420 行 · 第 1/2 页

C
420
字号
/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana *                         University Research and Technology *                         Corporation.  All rights reserved. * Copyright (c) 2004-2006 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 "ompi/op/op.h"#include "coll_tuned.h"#include "coll_tuned_topo.h"#include "coll_tuned_util.h"/* * Barrier is ment to be a synchronous operation, as some BTLs can mark  * a request done before its passed to the NIC and progress might not be made  * elsewhere we cannot allow a process to exit the barrier until its last  * [round of] sends are completed. * * It is last round of sends rather than 'last' individual send as each pair of  * peers can use different channels/devices/btls and the receiver of one of  * these sends might be forced to wait as the sender * leaves the collective and does not make progress until the next mpi call  * *//* * Simple double ring version of barrier * * synchronous gurantee made by last ring of sends are synchronous * */int ompi_coll_tuned_barrier_intra_doublering(struct ompi_communicator_t *comm){    int rank, size;    int err=0, line=0;    int left, right;    rank = ompi_comm_rank(comm);    size = ompi_comm_size(comm);    OPAL_OUTPUT((ompi_coll_tuned_stream,"ompi_coll_tuned_barrier_intra_doublering rank %d", rank));      left = ((rank-1)%size);    right = ((rank+1)%size);    if (rank > 0) { /* receive message from the left */        err = MCA_PML_CALL(recv((void*)NULL, 0, MPI_BYTE, left,                                 MCA_COLL_BASE_TAG_BARRIER, comm,                                 MPI_STATUS_IGNORE));        if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl; }    }    /* Send message to the right */    err = MCA_PML_CALL(send((void*)NULL, 0, MPI_BYTE, right,                             MCA_COLL_BASE_TAG_BARRIER,                             MCA_PML_BASE_SEND_STANDARD, comm));    if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl;  }    /* root needs to receive from the last node */    if (rank == 0) {        err = MCA_PML_CALL(recv((void*)NULL, 0, MPI_BYTE, left,                                 MCA_COLL_BASE_TAG_BARRIER, comm,                                 MPI_STATUS_IGNORE));        if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl; }    }    /* Allow nodes to exit */    if (rank > 0) { /* post Receive from left */        err = MCA_PML_CALL(recv((void*)NULL, 0, MPI_BYTE, left,                                 MCA_COLL_BASE_TAG_BARRIER, comm,                                 MPI_STATUS_IGNORE));        if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl; }    }    /* send message to the right one */    err = MCA_PML_CALL(send((void*)NULL, 0, MPI_BYTE, right,                             MCA_COLL_BASE_TAG_BARRIER,                             MCA_PML_BASE_SEND_SYNCHRONOUS, comm));    if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl;  }     /* rank 0 post receive from the last node */    if (rank == 0) {        err = MCA_PML_CALL(recv((void*)NULL, 0, MPI_BYTE, left,                                 MCA_COLL_BASE_TAG_BARRIER, comm,                                 MPI_STATUS_IGNORE));        if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl;  }    }    return MPI_SUCCESS; err_hndl:    OPAL_OUTPUT((ompi_coll_tuned_stream,"%s:%4d\tError occurred %d, rank %2d",                  __FILE__, line, err, rank));    return err;}/* * To make synchronous, uses sync sends and sync sendrecvs */int ompi_coll_tuned_barrier_intra_recursivedoubling(struct ompi_communicator_t *comm){    int rank, size, adjsize;    int err, line;    int mask, remote;    rank = ompi_comm_rank(comm);    size = ompi_comm_size(comm);    OPAL_OUTPUT((ompi_coll_tuned_stream,                 "ompi_coll_tuned_barrier_intra_recursivedoubling rank %d",                  rank));    /* do nearest power of 2 less than size calc */    for( adjsize = 1; adjsize <= size; adjsize <<= 1 );    adjsize >>= 1;    /* if size is not exact power of two, perform an extra step */    if (adjsize != size) {        if (rank >= adjsize) {            /* send message to lower ranked node */            remote = rank - adjsize;            err = ompi_coll_tuned_sendrecv_actual(NULL, 0, MPI_BYTE, remote,                                                  MCA_COLL_BASE_TAG_BARRIER,                                                  NULL, 0, MPI_BYTE, remote,                                                  MCA_COLL_BASE_TAG_BARRIER,                                                  comm, MPI_STATUS_IGNORE);            if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl;}        } else if (rank < (size - adjsize)) {            /* receive message from high level rank */            err = MCA_PML_CALL(recv((void*)NULL, 0, MPI_BYTE, rank+adjsize,                                    MCA_COLL_BASE_TAG_BARRIER, comm,                                     MPI_STATUS_IGNORE));            if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl;}        }    }    /* exchange messages */    if ( rank < adjsize ) {        mask = 0x1;        while ( mask < adjsize ) {            remote = rank ^ mask;            mask <<= 1;            if (remote >= adjsize) continue;            /* post receive from the remote node */            err = ompi_coll_tuned_sendrecv_actual(NULL, 0, MPI_BYTE, remote,                                                  MCA_COLL_BASE_TAG_BARRIER,                                                  NULL, 0, MPI_BYTE, remote,                                                  MCA_COLL_BASE_TAG_BARRIER,                                                  comm, MPI_STATUS_IGNORE);            if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl;}        }    }    /* non-power of 2 case */    if (adjsize != size) {        if (rank < (size - adjsize)) {            /* send enter message to higher ranked node */            remote = rank + adjsize;            err = MCA_PML_CALL(send((void*)NULL, 0, MPI_BYTE, remote,                                     MCA_COLL_BASE_TAG_BARRIER,                                     MCA_PML_BASE_SEND_SYNCHRONOUS, comm));            if (err != MPI_SUCCESS) { line = __LINE__; goto err_hndl;}        }    }    return MPI_SUCCESS; err_hndl:    OPAL_OUTPUT((ompi_coll_tuned_stream,"%s:%4d\tError occurred %d, rank %2d",                 __FILE__, line, err, rank));    return err;}/* * To make synchronous, uses sync sends and sync sendrecvs */int ompi_coll_tuned_barrier_intra_bruck(struct ompi_communicator_t *comm){    int rank, size;    int distance, to, from;    int err, line = 0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?