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

📄 commutil.c

📁 fortran并行计算包
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	if (own_mask) {	    /* There is a chance that we've found a context id */	    /* MPIU_THREAD_SINGLE_CS_ENTER("context_id"); */	    /* Find_context_bit updates the context array if it finds a match */	    context_id = MPIR_Find_context_bit( local_mask );	    MPIU_DBG_MSG_D( COMM, VERBOSE, 			    "Context id is now %d", 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 {		/* 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.		   We need to ensure that any other threads have the 		   opportunity to run.  We do this by releasing the single		   mutex, yielding, and then reaquiring the mutex.		   We might want to do something more sophisticated, such		   as using a condition variable (if we know for sure that		   there is another thread on this process that is waiting).		*/		MPID_Thread_mutex_unlock(&MPIR_ThreadInfo.global_mutex);		MPID_Thread_yield();		MPID_Thread_mutex_lock(&MPIR_ThreadInfo.global_mutex);	    }	    mask_in_use = 0;	    /* MPIU_THREAD_SINGLE_CS_EXIT("context_id"); */	}	else {	    /* As above, force this thread to yield */	    MPID_Thread_mutex_unlock(&MPIR_ThreadInfo.global_mutex);	    MPID_Thread_yield();	    MPID_Thread_mutex_lock(&MPIR_ThreadInfo.global_mutex);	}    }    MPIU_DBG_MSG_S(COMM,VERBOSE,"Context mask = %s",MPIR_ContextMaskToStr());    MPIR_Nest_decr();    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GET_CONTEXTID);    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.*//*  * This uses the thread-safe (if necessary) routine to get a context id * and does not need its own thread-safe version. */#undef FUNCNAME#define FUNCNAME MPIR_Get_intercomm_contextid#undef FCNAME#define FCNAME "MPIR_Get_intercomm_contextid"int MPIR_Get_intercomm_contextid( MPID_Comm *comm_ptr, int *context_id, 				  int *recvcontext_id ){    int mycontext_id, remote_context_id;    int mpi_errno = MPI_SUCCESS;    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) */    MPIU_THREADPRIV_DECL;    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);    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 );*/    mycontext_id = MPIR_Get_contextid( comm_ptr->local_comm );    if (mycontext_id == 0) {	goto fn_fail;    }    MPIU_THREADPRIV_GET;    /* 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( &mycontext_id, 1, MPI_INT, 0, tag,		       &remote_context_id, 1, MPI_INT, 0, tag, 		       comm_ptr->handle, MPI_STATUS_IGNORE );    }    /* Make sure that all of the local processes now have this       id */    MPIR_Nest_incr();    NMPI_Bcast( &remote_context_id, 1, MPI_INT, 		0, comm_ptr->local_comm->handle );    MPIR_Nest_decr();    /* printf( "intercomm context = %d\n", remote_context_id ); */    *context_id     = remote_context_id;    *recvcontext_id = mycontext_id; fn_fail:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_GET_INTERCOMM_CONTEXTID);    return mpi_errno;}#undef FUNCNAME#define FUNCNAME MPIR_Free_contextid#undef FCNAME#define FCNAME "MPIR_Free_contextid"void MPIR_Free_contextid( int context_id ){    int idx, bitpos;    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_FREE_CONTEXTID);        MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_FREE_CONTEXTID);    /* 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-- */    /* Check that this context id has been allocated */#if 0    /* FIXME: This test should be included */    if ( (context_mask[idx] & (0x1 << bitpos)) != 0) {	MPID_Abort( 0, MPI_ERR_INTERN, 1, 		    "In MPIR_Free_contextid, the context id is not in use" );    }#endif    /* MT: Note that this update must be done atomically in the multithreaded       case.  In the "one, single lock" implementation, that lock is indeed       held when this operation is called. */    context_mask[idx] |= (0x1 << bitpos);    MPIU_DBG_MSG_FMT(COMM,VERBOSE,(MPIU_DBG_FDEST,			"Freed context %d, mask[%d] bit %d\n", 			context_id, idx, bitpos ) );    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_FREE_CONTEXTID);}/* * 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 (local group * in the ) input communicator, copy only the first size elements.   * If this process is not a member, return a null pointer in outcomm_ptr. * This is only supported in the case where the communicator is in  * Intracomm (not an Intercomm).  Note that this is all that is required * for cart_create and graph_create. * * Used by cart_create, graph_create, and dup_create  */#undef FUNCNAME#define FUNCNAME MPIR_Comm_copy#undef FCNAME#define FCNAME "MPIR_Comm_copy"int MPIR_Comm_copy( MPID_Comm *comm_ptr, int size, MPID_Comm **outcomm_ptr ){    int mpi_errno = MPI_SUCCESS;    int new_context_id, new_recvcontext_id;    MPID_Comm *newcomm_ptr;    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_COPY);    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_COPY);    /* 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) {	mpi_errno = 	    MPIR_Get_intercomm_contextid( 		 comm_ptr, &new_context_id, &new_recvcontext_id );    }    else {	new_context_id = MPIR_Get_contextid( comm_ptr );	new_recvcontext_id = new_context_id;    }    /* --BEGIN ERROR HANDLING-- */    if (new_context_id == 0 || mpi_errno != MPI_SUCCESS) {	mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,               FCNAME, __LINE__, MPI_ERR_OTHER, "**toomanycomm", 0 );	goto fn_fail;    }    /* --END ERROR HANDLING-- */    /* This is the local size, not the remote size, in the case of       an intercomm */    if (comm_ptr->rank >= size) {	*outcomm_ptr = 0;	goto fn_exit;    }    /* We're left with the processes that will have a non-null communicator.       Create the object, initialize the data, and return the result */    mpi_errno = MPIR_Comm_create( &newcomm_ptr );    if (mpi_errno) goto fn_fail;    newcomm_ptr->context_id     = new_context_id;    newcomm_ptr->recvcontext_id = new_recvcontext_id;    /* Save the kind of the communicator */    newcomm_ptr->comm_kind   = comm_ptr->comm_kind;    newcomm_ptr->local_comm  = 0;    /* There are two cases here - size is the same as the old communicator,       or it is smaller.  If the size is the same, we can just add a reference.       Otherwise, we need to create a new VCRT.  Note that this is the       test that matches the test on rank above. */    if (size == comm_ptr->local_size) {	/* Duplicate the VCRT references */	MPID_VCRT_Add_ref( comm_ptr->vcrt );	newcomm_ptr->vcrt = comm_ptr->vcrt;	newcomm_ptr->vcr  = comm_ptr->vcr;    }    else {	int i;	/* The "remote" vcr gets the shortened vcrt */	MPID_VCRT_Create( size, &newcomm_ptr->vcrt );	MPID_VCRT_Get_ptr( newcomm_ptr->vcrt, 			   &newcomm_ptr->vcr );	for (i=0; i<size; i++) {	    /* For rank i in the new communicator, find the corresponding	       rank in the input communicator */	    MPID_VCR_Dup( comm_ptr->vcr[i], &newcomm_ptr->vcr[i] );	}    }    /* 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->rank        = comm_ptr->rank;    if (comm_ptr->comm_kind == MPID_INTERCOMM) {	newcomm_ptr->local_size  = comm_ptr->local_size;	newcomm_ptr->remote_size = comm_ptr->remote_size;    }    else {	newcomm_ptr->local_size  = size;	newcomm_ptr->remote_size = size;    }    /* Inherit the error handler (if any) */    newcomm_ptr->errhandler = comm_ptr->errhandler;    if (comm_ptr->errhandler) {	MPIR_Errhandler_add_ref( comm_ptr->errhandler );    }    /* Notify the device of the new communicator */    MPID_Dev_comm_create_hook(newcomm_ptr);	        /* Start with no attributes on this communicator */    newcomm_ptr->attributes = 0;    *outcomm_ptr = newcomm_ptr; fn_fail: fn_exit:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_COPY);    return mpi_errno;}/* Release a reference to a communicator.  If there are no pending   references, delete the communicator and recover all storage and    context ids */#undef FUNCNAME #define FUNCNAME MPIR_Comm_release#undef FCNAME#define FCNAME "MPIR_Comm_release"int MPIR_Comm_release(MPID_Comm * comm_ptr, int isDisconnect){    int mpi_errno = MPI_SUCCESS;    int inuse;    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_RELEASE);    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_RELEASE);        MPIR_Comm_release_ref( comm_ptr, &inuse );    if (!inuse) {	/* Remove the attributes, executing the attribute delete routine.             Do this only if the attribute functions are defined. 	   This must be done first, because if freeing the attributes	   returns an error, the communicator is not freed */	if (MPIR_Process.attr_free && comm_ptr->attributes) {	    /* Temporarily add a reference to this communicator because                the attr_free code requires a valid communicator */ 	    MPIU_Object_add_ref( comm_ptr ); 	    mpi_errno = MPIR_Process.attr_free( comm_ptr->handle, 						comm_ptr->attributes );	    /* Release the temporary reference added before the call to                attr_free */ 	    MPIU_Object_release_ref( comm_ptr, &inuse); 	}	if (mpi_errno == MPI_SUCCESS) {	    /* If this communicator is our parent, and we're disconnecting	       from the parent, mark that fact */	    if (MPIR_Process.comm_parent == comm_ptr)		MPIR_Process.comm_parent = NULL;	    /* 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, isDisconnect);	    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, isDisconnect);		if (mpi_errno != MPI_SUCCESS) {		    MPIU_ERR_POP(mpi_errno);		}                if (comm_ptr->local_comm)                     MPIR_Comm_release(comm_ptr->local_comm, isDisconnect );            }	    /* Free the context value */	    MPIR_Free_contextid( comm_ptr->recvcontext_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 );  	    	    /* Remove from the list of active communicators if 	       we are supporting message-queue debugging.  We make this	       conditional on having debugger support since the	       operation is not constant-time */	    MPIR_COMML_FORGET( comm_ptr );	}	else {	    /* If the user attribute free function returns an error,	       then do not free the communicator */	    MPIR_Comm_add_ref( comm_ptr );	}    } fn_exit:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_RELEASE);    return mpi_errno; fn_fail:    goto fn_exit;}

⌨️ 快捷键说明

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