commutil.c

来自「mpi并行计算的c++代码 可用vc或gcc编译通过 可以用来搭建并行计算试验环」· C语言 代码 · 共 617 行 · 第 1/2 页

C
617
字号
	    lowestContextId = comm_ptr->context_id;	    MPIU_DBG_PRINTF_CLASS( MPIU_DBG_COMM | MPIU_DBG_CONTEXTID, 2, 				   ( "Copied local_mask\n" ) );	}	MPID_Common_thread_unlock();		/* Now, try to get a context id */	MPIR_Nest_incr();	/* Comm must be an intracommunicator */	NMPI_Allreduce( MPI_IN_PLACE, local_mask, MAX_CONTEXT_MASK, MPI_INT, 			MPI_BAND, comm_ptr->handle );	MPIR_Nest_decr();	if (own_mask) {	    /* There is a chance that we've found a context id */	    MPID_Common_thread_lock();	    /* Find_context_bit updates the context array if it finds a match */	    context_id = MPIR_Find_context_bit( local_mask );	    MPIU_DBG_PRINTF_CLASS( MPIU_DBG_COMM | MPIU_DBG_CONTEXTID, 1, 				   ( "Context id is now %d\n", context_id ) );	    if (context_id > 0) {		/* If we were the lowest context id, reset the value to		   allow the other threads to compete for the mask */		if (lowestContextId == comm_ptr->context_id) {		    lowestContextId = MPIR_MAXID;		    /* Else leave it alone; there is another thread waiting */		}	    }	    /* else we did not find a context id. Give up the mask in case	       there is another thread (with a lower context id) waiting for	       it */	    mask_in_use = 0;	    MPID_Common_thread_unlock();	}    }    return context_id;}#endif/* Get a context for a new intercomm.  There are two approaches    here (for MPI-1 codes only)   (a) Each local group gets a context; the groups exchange, and       the low value is accepted and the high one returned.  This       works because the context ids are taken from the same pool.   (b) Form a temporary intracomm over all processes and use that       with the regular algorithm.      In some ways, (a) is the better approach because it is the one that   extends to MPI-2 (where the last step, returning the context, is    not used and instead separate send and receive context id value    are kept).  For this reason, we'll use (a).   Even better is to separate the local and remote context ids.  Then   each group of processes can manage their context ids separately.*//* FIXME : This approach for intercomm context will not work for MPI-2 * * This uses the thread-safe (if necessary) routine to get a context id * and does not need its own thread-safe version. */int MPIR_Get_intercomm_contextid( MPID_Comm *comm_ptr ){    int context_id, remote_context_id, final_context_id;    int tag = 31567; /* FIXME  - we need an internal tag or 		        communication channel.  Can we use a different		        context instead?.  Or can we use the tag 		        provided in the intercomm routine? (not on a dup, 			but in that case it can use the collective context) */    if (!comm_ptr->local_comm) {	/* Manufacture the local communicator */	MPIR_Setup_intercomm_localcomm( comm_ptr );    }    /*printf( "local comm size is %d and intercomm local size is %d\n",      comm_ptr->local_comm->local_size, comm_ptr->local_size );*/    context_id = MPIR_Get_contextid( comm_ptr->local_comm );    if (context_id == 0) return 0;    /* MPIC routine uses an internal context id.  The local leads (process 0)       exchange data */    remote_context_id = -1;    if (comm_ptr->rank == 0) {	MPIC_Sendrecv( &context_id, 1, MPI_INT, 0, tag,		       &remote_context_id, 1, MPI_INT, 0, tag, 		       comm_ptr->handle, MPI_STATUS_IGNORE );	/* FIXME : We need to do something with the context ids.  For 	   MPI1, we can just take the min of the two context ids and	   use that value.  For MPI2, we'll need to have separate	   send and receive context ids */	if (remote_context_id < context_id)	    final_context_id = remote_context_id;	else 	    final_context_id = context_id;    }    /* Make sure that all of the local processes now have this       id */    MPIR_Nest_incr();    NMPI_Bcast( &final_context_id, 1, MPI_INT, 		0, comm_ptr->local_comm->handle );    MPIR_Nest_decr();    /* FIXME : If we did not choose this context, free it.  We won't do this       once we have MPI2 intercomms (at least, not for intercomms that       are not subsets of MPI_COMM_WORLD) */    if (final_context_id != context_id) {	MPIR_Free_contextid( context_id );    }    /* printf( "intercomm context = %d\n", final_context_id ); */    return final_context_id;}void MPIR_Free_contextid( int context_id ){    int idx, bitpos;    /* Convert the context id to the bit position */    /* printf( "Freed id = %d\n", context_id ); */    context_id >>= 2;       /* Remove the shift of a factor of four */    idx    = context_id / 32;    bitpos = context_id % 32;    /* --BEGIN ERROR HANDLING-- */    if (idx < 0 || idx >= MAX_CONTEXT_MASK) {	MPID_Abort( 0, MPI_ERR_INTERN, 1, 		    "In MPIR_Free_contextid, idx is out of range" );    }    /* --END ERROR HANDLING-- */    /* This update must be done atomically in the multithreaded case */#if MPID_MAX_THREAD_LEVEL <= MPI_THREAD_SERIALIZED    context_mask[idx] |= (0x1 << bitpos);#else    MPID_Common_thread_lock();    context_mask[idx] |= (0x1 << bitpos);    MPID_Common_thread_unlock();#endif#ifdef MPICH_DEBUG_INTERNAL    if (MPIR_IDebug("context")) {	DBG_FPRINTF( stderr, "Freed context %d\n", context_id );	DBG_FPRINTF( stderr, "mask[%d] bit %d\n", idx, bitpos );    }#endif}/* * Copy a communicator, including creating a new context and copying the * virtual connection tables and clearing the various fields. * Does *not* copy attributes.  If size is < the size of the input * communicator, copy only the first size elements.  If this process * is not a member, return a null pointer in outcomm_ptr. * * Used by comm_create, cart_create, graph_create, and dup_create  */int MPIR_Comm_copy( MPID_Comm *comm_ptr, int size, MPID_Comm **outcomm_ptr ){    int mpi_errno = MPI_SUCCESS;    int new_context_id;    MPID_Comm *newcomm_ptr;    /* Get a new context first.  We need this to be collective over the       input communicator */    /* If there is a context id cache in oldcomm, use it here.  Otherwise,       use the appropriate algorithm to get a new context id.  Be careful       of intercomms here */    if (comm_ptr->comm_kind == MPID_INTERCOMM) {	new_context_id = MPIR_Get_intercomm_contextid( comm_ptr );    }    else {	new_context_id = MPIR_Get_contextid( comm_ptr );    }    /* --BEGIN ERROR HANDLING-- */    if (new_context_id == 0) {	mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,               "MPIR_Comm_copy", __LINE__, MPI_ERR_OTHER, "**toomanycomm", 0 );	return mpi_errno;    }    /* --END ERROR HANDLING-- */    if (comm_ptr->rank >= size) {	*outcomm_ptr = 0;	return MPI_SUCCESS;    }    /* We're left with the processes that will have a non-null communicator.       Create the object, initialize the data, and return the result */    newcomm_ptr = (MPID_Comm *)MPIU_Handle_obj_alloc( &MPID_Comm_mem );    /* --BEGIN ERROR HANDLING-- */    if (!newcomm_ptr) {	mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,                      "MPIR_Comm_copy", __LINE__, MPI_ERR_OTHER, "**nomem", 0 );	return mpi_errno;    }    /* --END ERROR HANDLING-- */    MPIU_Object_set_ref( newcomm_ptr, 1 );    newcomm_ptr->context_id = new_context_id;    /* Save the kind of the communicator */    newcomm_ptr->comm_kind   = comm_ptr->comm_kind;    newcomm_ptr->local_comm  = 0;        /* Duplicate the VCRT references */    MPID_VCRT_Add_ref( comm_ptr->vcrt );    newcomm_ptr->vcrt = comm_ptr->vcrt;    newcomm_ptr->vcr  = comm_ptr->vcr;    /* If it is an intercomm, duplicate the local vcrt references */    if (comm_ptr->comm_kind == MPID_INTERCOMM) {	MPID_VCRT_Add_ref( comm_ptr->local_vcrt );	newcomm_ptr->local_vcrt = comm_ptr->local_vcrt;	newcomm_ptr->local_vcr  = comm_ptr->local_vcr;    }    /* Set the sizes and ranks */    newcomm_ptr->remote_size = comm_ptr->remote_size;    newcomm_ptr->rank        = comm_ptr->rank;    newcomm_ptr->local_size  = comm_ptr->local_size;    /* More advanced version: if the group is available, dup it by        increasing the reference count */    newcomm_ptr->local_group  = 0;    newcomm_ptr->remote_group = 0;    /* Inherit the error handler (if any) */    newcomm_ptr->errhandler = comm_ptr->errhandler;    if (comm_ptr->errhandler) {	MPIU_Object_add_ref( comm_ptr->errhandler );    }    /* We could also inherit the communicator function pointer */    newcomm_ptr->coll_fns = 0;    /* Similarly, we could also inherit the topology function pointer */    newcomm_ptr->topo_fns = 0;    /* We do *not* inherit any name */    newcomm_ptr->name[0] = 0;    /* Start with no attributes on this communicator */    newcomm_ptr->attributes = 0;    *outcomm_ptr = newcomm_ptr;    return MPI_SUCCESS;}int MPIR_Comm_release(MPID_Comm * comm_ptr){    static const char FCNAME[] = "MPIR_Comm_release";    int mpi_errno = MPI_SUCCESS;    int inuse;        MPIU_Object_release_ref( comm_ptr, &inuse);    if (!inuse) {        if (MPIR_Process.comm_parent == comm_ptr)            MPIR_Process.comm_parent = NULL;	/* Remove the attributes, executing the attribute delete routine.             Do this only if the attribute functions are defined. */	if (MPIR_Process.attr_free && comm_ptr->attributes) {	    mpi_errno = MPIR_Process.attr_free( comm_ptr->handle, 						comm_ptr->attributes );	}	if (mpi_errno == MPI_SUCCESS) {	    /* Notify the device that the communicator is about to be 	       destroyed */	    MPID_Dev_comm_destroy_hook(comm_ptr);	    	    /* Free the VCRT */	    mpi_errno = MPID_VCRT_Release(comm_ptr->vcrt);	    if (mpi_errno != MPI_SUCCESS) {		MPIU_ERR_POP(mpi_errno);	    }            if (comm_ptr->comm_kind == MPID_INTERCOMM) {                mpi_errno = MPID_VCRT_Release(comm_ptr->local_vcrt);		if (mpi_errno != MPI_SUCCESS) {		    MPIU_ERR_POP(mpi_errno);		}                if (comm_ptr->local_comm)                     MPIR_Comm_release(comm_ptr->local_comm);            }	    /* Free the context value */	    MPIR_Free_contextid( comm_ptr->context_id );	    /* Free the local and remote groups, if they exist */            if (comm_ptr->local_group)                MPIR_Group_release(comm_ptr->local_group);            if (comm_ptr->remote_group)                MPIR_Group_release(comm_ptr->remote_group);  	    MPIU_Handle_obj_free( &MPID_Comm_mem, comm_ptr );  	}	else {	    /* If the user attribute free function returns an error,	       then do not free the communicator */	    MPIU_Object_add_ref( comm_ptr );	}    } fn_exit:    return mpi_errno; fn_fail:    goto fn_exit;}

⌨️ 快捷键说明

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