⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intercomm_merge.c

📁 fortran并行计算包
💻 C
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * *  (C) 2001 by Argonne National Laboratory. *      See COPYRIGHT in top-level directory. */#include "mpiimpl.h"#include "mpicomm.h"/* -- Begin Profiling Symbol Block for routine MPI_Intercomm_merge */#if defined(HAVE_PRAGMA_WEAK)#pragma weak MPI_Intercomm_merge = PMPI_Intercomm_merge#elif defined(HAVE_PRAGMA_HP_SEC_DEF)#pragma _HP_SECONDARY_DEF PMPI_Intercomm_merge  MPI_Intercomm_merge#elif defined(HAVE_PRAGMA_CRI_DUP)#pragma _CRI duplicate MPI_Intercomm_merge as PMPI_Intercomm_merge#endif/* -- End Profiling Symbol Block *//* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build   the MPI routines */#ifndef MPICH_MPI_FROM_PMPI#undef MPI_Intercomm_merge#define MPI_Intercomm_merge PMPI_Intercomm_merge#endif#undef FUNCNAME#define FUNCNAME MPI_Intercomm_merge/*@MPI_Intercomm_merge - Creates an intracommuncator from an intercommunicatorInput Parameters:+ comm - Intercommunicator (handle)- high - Used to order the groups within comm (logical)  when creating the new communicator.  This is a boolean value; the group  that sets high true has its processes ordered `after` the group that sets   this value to false.  If all processes in the intercommunicator provide  the same value, the choice of which group is ordered first is arbitrary.Output Parameter:. comm_out - Created intracommunicator (handle)Notes: While all processes may provide the same value for the 'high' parameter, this requires the MPI implementation to determine which group of  processes should be ranked first. .N ThreadSafe.N FortranAlgorithm:.Es.i Allocate contexts .i Local and remote group leaders swap high values.i Determine the high value..i Merge the two groups and make the intra-communicator.Ee.N Errors.N MPI_SUCCESS.N MPI_ERR_COMM.N MPI_ERR_EXHAUSTED.seealso: MPI_Intercomm_create, MPI_Comm_free@*/int MPI_Intercomm_merge(MPI_Comm intercomm, int high, MPI_Comm *newintracomm){    static const char FCNAME[] = "MPI_Intercomm_merge";    int mpi_errno = MPI_SUCCESS;    MPID_Comm *comm_ptr = NULL;    MPID_Comm *newcomm_ptr;    int  local_high, remote_high, i, j, new_size, new_context_id;    MPIU_THREADPRIV_DECL;    MPID_MPI_STATE_DECL(MPID_STATE_MPI_INTERCOMM_MERGE);    MPIR_ERRTEST_INITIALIZED_ORDIE();        MPIU_THREAD_SINGLE_CS_ENTER("comm");      MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_INTERCOMM_MERGE);    MPIU_THREADPRIV_GET;        /* Validate parameters, especially handles needing to be converted */#   ifdef HAVE_ERROR_CHECKING    {        MPID_BEGIN_ERROR_CHECKS;        {	    MPIR_ERRTEST_COMM(intercomm, mpi_errno);            if (mpi_errno != MPI_SUCCESS) goto fn_fail;	}        MPID_END_ERROR_CHECKS;    }#   endif /* HAVE_ERROR_CHECKING */    /* Convert MPI object handles to object pointers */    MPID_Comm_get_ptr( intercomm, comm_ptr );        /* Validate parameters and objects (post conversion) */#   ifdef HAVE_ERROR_CHECKING    {        MPID_BEGIN_ERROR_CHECKS;        {            /* Validate comm_ptr */            MPID_Comm_valid_ptr( comm_ptr, mpi_errno );	    /* If comm_ptr is not valid, it will be reset to null */	    if (comm_ptr && comm_ptr->comm_kind != MPID_INTERCOMM) {		mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, 		    MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_COMM,						  "**commnotinter", 0 );	    }            if (mpi_errno) goto fn_fail;        }        MPID_END_ERROR_CHECKS;    }#   endif /* HAVE_ERROR_CHECKING */    /* ... body of routine ... */        /* Make sure that we have a local intercommunicator */    if (!comm_ptr->local_comm) {	/* Manufacture the local communicator */	MPIR_Setup_intercomm_localcomm( comm_ptr );    }#   ifdef HAVE_ERROR_CHECKING    {        MPID_BEGIN_ERROR_CHECKS;        {	    int acthigh;	    /* Check for consistent valus of high in each local group.	     The Intel test suite checks for this; it is also an easy	     error to make */	    acthigh = high ? 1 : 0;   /* Clamp high into 1 or 0 */	    MPIR_Nest_incr();	    mpi_errno = NMPI_Allreduce( MPI_IN_PLACE, &acthigh, 1, MPI_INT, 				MPI_SUM, comm_ptr->local_comm->handle );	    MPIR_Nest_decr();	    if (mpi_errno) goto fn_fail;	    /* acthigh must either == 0 or the size of the local comm */	    if (acthigh != 0 && acthigh != comm_ptr->local_size) {		mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, 		    MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, 						  "**notsame",						  "**notsame %s %s", "high", 						  "MPI_Intercomm_merge" );		goto fn_fail;	    }        }        MPID_END_ERROR_CHECKS;    }#   endif /* HAVE_ERROR_CHECKING */    /* Find the "high" value of the other group of processes.  This       will be used to determine which group is ordered first in       the generated communicator.  high is logical */    local_high = high;    if (comm_ptr->rank == 0) {	/* This routine allows use to use the collective communication	   context rather than the point-to-point context. */	MPIC_Sendrecv( &local_high, 1, MPI_INT, 0, 0, 		       &remote_high, 1, MPI_INT, 0, 0, intercomm, 		       MPI_STATUS_IGNORE );		/* If local_high and remote_high are the same, then order is arbitrary.	   we use the gpids of the rank 0 member of the local and remote	   groups to choose an order in this case. */	if (local_high == remote_high) {	    int ingpid[2], outgpid[2];	    	    MPID_GPID_Get( comm_ptr, 0, ingpid );	    MPIC_Sendrecv( ingpid, 2, MPI_INT, 0, 1,			   outgpid, 2, MPI_INT, 0, 1, intercomm, 			   MPI_STATUS_IGNORE );	    /* Note that the gpids cannot be the same because we are 	       starting from a valid intercomm */	    if (ingpid[0] < outgpid[0] ||		(ingpid[0] == outgpid[0] && ingpid[1] < outgpid[1])) {		local_high = 0;	    }	    else {		local_high = 1;		/* req#3930: The merge algorithm will deadlock if the gpids are inadvertently the		   same due to implementation bugs in the MPID_GPID_Get() function */		MPIU_Assert( !(ingpid[0] == outgpid[0] && ingpid[1] == outgpid[1]) );	    }	}    }    /*        All processes in the local group now need to get the        value of local_high, which may have changed if both groups       of processes had the same value for high    */    MPIR_Nest_incr();    mpi_errno = NMPI_Bcast( &local_high, 1, MPI_INT, 0, 			    comm_ptr->local_comm->handle );    MPIR_Nest_decr();    if (mpi_errno) goto fn_fail;    mpi_errno = MPIR_Comm_create( &newcomm_ptr );    if (mpi_errno) goto fn_fail;    new_size = comm_ptr->local_size + comm_ptr->remote_size;    /* FIXME: For the intracomm, we need a consistent context id.         That means that one of the two groups needs to use        the recvcontext_id and the other must use the context_id */    if (local_high) {	newcomm_ptr->context_id	= comm_ptr->recvcontext_id + 2; /* See below */    }    else {	newcomm_ptr->context_id	= comm_ptr->context_id + 2; /* See below */    }    newcomm_ptr->recvcontext_id	= newcomm_ptr->context_id;    newcomm_ptr->remote_size	= newcomm_ptr->local_size   = new_size;    newcomm_ptr->rank		= -1;    newcomm_ptr->comm_kind	= MPID_INTRACOMM;    /* Now we know which group comes first.  Build the new vcr        from the existing vcrs */    MPID_VCRT_Create( new_size, &newcomm_ptr->vcrt );    MPID_VCRT_Get_ptr( newcomm_ptr->vcrt, &newcomm_ptr->vcr );    if (local_high) {	/* remote group first */	j = 0;	for (i=0; i<comm_ptr->remote_size; i++) {	    MPID_VCR_Dup( comm_ptr->vcr[i], &newcomm_ptr->vcr[j++] );	}	for (i=0; i<comm_ptr->local_size; i++) {	    if (i == comm_ptr->rank) newcomm_ptr->rank = j;	    MPID_VCR_Dup( comm_ptr->local_vcr[i], &newcomm_ptr->vcr[j++] );	}    }    else {	/* local group first */	j = 0;	for (i=0; i<comm_ptr->local_size; i++) {	    if (i == comm_ptr->rank) newcomm_ptr->rank = j;	    MPID_VCR_Dup( comm_ptr->local_vcr[i], &newcomm_ptr->vcr[j++] );	}	for (i=0; i<comm_ptr->remote_size; i++) {	    MPID_VCR_Dup( comm_ptr->vcr[i], &newcomm_ptr->vcr[j++] );	}    }    /* We've setup a temporary context id, based on the context id       used by the intercomm.  This allows us to perform the allreduce       operations within the context id algorithm, since we already       have a valid (almost - see comm_create_hook) communicator.    */    /* printf( "About to get context id \n" ); fflush( stdout ); */    /* In the multi-threaded case, MPIR_Get_contextid assumes that the       calling routine already holds the single criticial section */    new_context_id = MPIR_Get_contextid( newcomm_ptr );    MPIU_ERR_CHKANDJUMP(new_context_id == 0,mpi_errno,MPI_ERR_OTHER,			"**toomanycomm" );    newcomm_ptr->context_id	= new_context_id;    newcomm_ptr->recvcontext_id	= new_context_id;    /* Notify the device of this new communicator */    MPID_Dev_comm_create_hook( newcomm_ptr );    *newintracomm = newcomm_ptr->handle;    /* ... end of body of routine ... */      fn_exit:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_INTERCOMM_MERGE);    MPIU_THREAD_SINGLE_CS_EXIT("comm");    return mpi_errno;  fn_fail:    /* --BEGIN ERROR HANDLING-- */#   ifdef HAVE_ERROR_CHECKING    {	mpi_errno = MPIR_Err_create_code(	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, 	    "**mpi_intercomm_merge",	    "**mpi_intercomm_merge %C %d %p", intercomm, high, newintracomm);    }#   endif    mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );    goto fn_exit;    /* --END ERROR HANDLING-- */}

⌨️ 快捷键说明

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