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

📄 mpid_type_struct.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 <mpid_dataloop.h>#include <stdlib.h>#include <limits.h>#undef MPID_STRUCT_FLATTEN_DEBUG#undef MPID_STRUCT_DEBUGstatic int MPID_Type_struct_alignsize(int count,				      MPI_Datatype *oldtype_array,				      MPI_Aint *displacement_array);/* MPID_Type_struct_alignsize * * This function guesses at how the C compiler would align a structure * with the given components. * * It uses these configure-time defines to do its magic: * - HAVE_MAX_INTEGER_ALIGNMENT - maximum byte alignment of integers * - HAVE_MAX_FP_ALIGNMENT      - maximum byte alignment of floating points * - HAVE_MAX_LONG_DOUBLE_FP_ALIGNMENT - maximum byte alignment with long *                                   doubles (if different from FP_ALIGNMENT) * - HAVE_MAX_DOUBLE_FP_ALIGNMENT - maximum byte alignment with doubles (if *                                  long double is different from FP_ALIGNMENT) * - HAVE_DOUBLE_POS_ALIGNMENT  - indicates that structures with doubles *                                are aligned differently if double isn't *                                at displacement 0 (e.g. PPC32/64). * - HAVE_LLINT_POS_ALIGNMENT   - same as above, for MPI_LONG_LONG_INT * * The different FP, DOUBLE, LONG_DOUBLE alignment case are necessary for * Cygwin on X86 (because long_double is 12 bytes, so double and long double * have different natural alignments).  Linux on X86, however, does not have * different rules for this case. */static int MPID_Type_struct_alignsize(int count,				      MPI_Datatype *oldtype_array,				      MPI_Aint *displacement_array){    int i, max_alignsize = 0, tmp_alignsize, derived_alignsize = 0;    for (i=0; i < count; i++)    {	/* shouldn't be called with an LB or UB, but we'll handle it nicely */	if (oldtype_array[i] == MPI_LB || oldtype_array[i] == MPI_UB) continue;	else if (HANDLE_GET_KIND(oldtype_array[i]) == HANDLE_KIND_BUILTIN)	{	    tmp_alignsize = MPID_Datatype_get_basic_size(oldtype_array[i]);#ifdef HAVE_DOUBLE_ALIGNMENT_EXCEPTION	    if (oldtype_array[i] == MPI_DOUBLE) {		tmp_alignsize = HAVE_DOUBLE_ALIGNMENT_EXCEPTION;	    }#endif	    switch(oldtype_array[i])	    {		case MPI_FLOAT:		case MPI_DOUBLE:		case MPI_LONG_DOUBLE:#if defined(HAVE_MAX_LONG_DOUBLE_FP_ALIGNMENT) && \    defined(HAVE_MAX_DOUBLE_FP_ALIGNMENT)		    if (oldtype_array[i] == MPI_LONG_DOUBLE) {			if (tmp_alignsize > HAVE_MAX_LONG_DOUBLE_FP_ALIGNMENT)			    tmp_alignsize = HAVE_MAX_LONG_DOUBLE_FP_ALIGNMENT;		    }		    else if (oldtype_array[i] == MPI_DOUBLE) {			if (tmp_alignsize > HAVE_MAX_DOUBLE_FP_ALIGNMENT)			    tmp_alignsize = HAVE_MAX_DOUBLE_FP_ALIGNMENT;		    }		    else {			/* HAVE_MAX_FP_ALIGNMENT may not be defined, hence commented */				/*			if (tmp_alignsize > HAVE_MAX_FP_ALIGNMENT)			    tmp_alignsize = HAVE_MAX_FP_ALIGNMENT;				*/		    }#elif defined(HAVE_MAX_FP_ALIGNMENT)		    if (tmp_alignsize > HAVE_MAX_FP_ALIGNMENT)			tmp_alignsize = HAVE_MAX_FP_ALIGNMENT;#endif		    #ifdef HAVE_DOUBLE_POS_ALIGNMENT		    /* sort of a hack, but so is this rule */		    if (oldtype_array[i] == MPI_DOUBLE &&			displacement_array[i] != (MPI_Aint) 0)		    {			tmp_alignsize = 4;		    }#endif		    break;		default:#ifdef HAVE_MAX_INTEGER_ALIGNMENT		    if (tmp_alignsize > HAVE_MAX_INTEGER_ALIGNMENT)			tmp_alignsize = HAVE_MAX_INTEGER_ALIGNMENT;#endif		    break;#ifdef HAVE_LLINT_POS_ALIGNMENT		    if (oldtype_array[i] == MPI_LONG_LONG_INT &&			displacement_array[i] != (MPI_Aint) 0)		    {			tmp_alignsize = 4;		    }#endif	    }	}	else	{	    MPID_Datatype *dtp;	    	    MPID_Datatype_get_ptr(oldtype_array[i], dtp);	    tmp_alignsize = dtp->alignsize;	    if (derived_alignsize < tmp_alignsize)		derived_alignsize = tmp_alignsize;	}	if (max_alignsize < tmp_alignsize) max_alignsize = tmp_alignsize;    }    return max_alignsize;}/*@  MPID_Type_struct - create a struct datatype   Input Parameters:+ count - number of blocks in vector. blocklength_array - number of elements in each block. displacement_array - offsets of blocks from start of type in bytes- oldtype_array - types (using handle) of datatypes on which vector is based  Output Parameters:. newtype - handle of new struct datatype  Return Value:  MPI_SUCCESS on success, MPI errno on failure.@*/int MPID_Type_struct(int count,		     int *blocklength_array,		     MPI_Aint *displacement_array,		     MPI_Datatype *oldtype_array,		     MPI_Datatype *newtype){    int mpi_errno = MPI_SUCCESS;    int i, old_are_contig = 1, definitely_not_contig = 0;    int found_sticky_lb = 0, found_sticky_ub = 0, found_true_lb = 0,	found_true_ub = 0, found_el_type = 0;    int el_sz = 0, size = 0;    MPI_Datatype el_type = MPI_DATATYPE_NULL;    MPI_Aint true_lb_disp = 0, true_ub_disp = 0, sticky_lb_disp = 0,	sticky_ub_disp = 0;    MPID_Datatype *new_dtp;    if (count == 0) return MPID_Type_zerolen(newtype);#ifdef MPID_STRUCT_DEBUG    MPIDI_Datatype_printf(oldtype_array[0], 1, displacement_array[0],			  blocklength_array[0], 1);    for (i=1; i < count; i++)    {	MPIDI_Datatype_printf(oldtype_array[i], 1, displacement_array[i],			      blocklength_array[i], 0);    }#endif    /* allocate new datatype object and handle */    new_dtp = (MPID_Datatype *) MPIU_Handle_obj_alloc(&MPID_Datatype_mem);    /* --BEGIN ERROR HANDLING-- */    if (!new_dtp)    {	mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,					 "MPID_Type_struct",					 __LINE__, MPI_ERR_OTHER,					 "**nomem", 0);	return mpi_errno;    }    /* --END ERROR HANDLING-- */    /* handle is filled in by MPIU_Handle_obj_alloc() */    MPIU_Object_set_ref(new_dtp, 1);    new_dtp->is_permanent = 0;    new_dtp->is_committed = 0;    new_dtp->attributes   = NULL;    new_dtp->cache_id     = 0;    new_dtp->name[0]      = 0;    new_dtp->contents     = NULL;    new_dtp->dataloop       = NULL;    new_dtp->dataloop_size  = -1;    new_dtp->dataloop_depth = -1;    new_dtp->hetero_dloop       = NULL;    new_dtp->hetero_dloop_size  = -1;    new_dtp->hetero_dloop_depth = -1;    /* check for junk struct with all zero blocks */    for (i=0; i < count; i++) if (blocklength_array[i] != 0) break;    if (i == count)    {	MPIU_Handle_obj_free(&MPID_Datatype_mem, new_dtp);	return MPID_Type_zerolen(newtype);    }    new_dtp->n_contig_blocks = 0;    for (i=0; i < count; i++)    {	int is_builtin =	    (HANDLE_GET_KIND(oldtype_array[i]) == HANDLE_KIND_BUILTIN);	MPI_Aint tmp_lb, tmp_ub, tmp_true_lb, tmp_true_ub;	int tmp_el_sz;	MPI_Datatype tmp_el_type;	MPID_Datatype *old_dtp = NULL;	/* Interpreting typemap to not include 0 blklen things, including	 * MPI_LB and MPI_UB. -- Rob Ross, 10/31/2005	 */	if (blocklength_array[i] == 0) continue;	if (is_builtin)	{	    tmp_el_sz   = MPID_Datatype_get_basic_size(oldtype_array[i]);	    tmp_el_type = oldtype_array[i];	    MPID_DATATYPE_BLOCK_LB_UB(blocklength_array[i],				      displacement_array[i],				      0,				      tmp_el_sz,				      tmp_el_sz,				      tmp_lb,				      tmp_ub);	    tmp_true_lb = tmp_lb;	    tmp_true_ub = tmp_ub;	    size += tmp_el_sz * blocklength_array[i];	    new_dtp->n_contig_blocks++;	}	else	{	    MPID_Datatype_get_ptr(oldtype_array[i], old_dtp);	    tmp_el_sz   = old_dtp->element_size;	    tmp_el_type = old_dtp->eltype;	    MPID_DATATYPE_BLOCK_LB_UB(blocklength_array[i],				      displacement_array[i],				      old_dtp->lb,				      old_dtp->ub,				      old_dtp->extent,				      tmp_lb,				      tmp_ub);	    tmp_true_lb = tmp_lb + (old_dtp->true_lb - old_dtp->lb);	    tmp_true_ub = tmp_ub + (old_dtp->true_ub - old_dtp->ub);	    size += old_dtp->size * blocklength_array[i];	    new_dtp->n_contig_blocks += old_dtp->n_contig_blocks;	}	/* element size and type */	if (oldtype_array[i] != MPI_LB && oldtype_array[i] != MPI_UB)	{	    if (found_el_type == 0)	    {		el_sz         = tmp_el_sz;		el_type       = tmp_el_type;		found_el_type = 1;	    }	    else if (el_sz != tmp_el_sz)	    {		el_sz = -1;		el_type = MPI_DATATYPE_NULL;	    }	    else if (el_type != tmp_el_type)	    {		/* Q: should we set el_sz = -1 even though the same? */		el_type = MPI_DATATYPE_NULL;	    }	}	/* keep lowest sticky lb */	if ((oldtype_array[i] == MPI_LB) ||	    (!is_builtin && old_dtp->has_sticky_lb))	{	    if (!found_sticky_lb)	    {		found_sticky_lb = 1;		sticky_lb_disp  = tmp_lb;	    }	    else if (sticky_lb_disp > tmp_lb)	    {		sticky_lb_disp = tmp_lb;	    }	}	/* keep highest sticky ub */	if ((oldtype_array[i] == MPI_UB) || 	    (!is_builtin && old_dtp->has_sticky_ub))	{	    if (!found_sticky_ub)	    {		found_sticky_ub = 1;		sticky_ub_disp  = tmp_ub;	    }	    else if (sticky_ub_disp < tmp_ub)	    {		sticky_ub_disp = tmp_ub;	    }	}	/* keep lowest true lb and highest true ub	 * 	 * note: checking for contiguity at the same time, to avoid	 *       yet another pass over the arrays	 */	if (oldtype_array[i] != MPI_UB && oldtype_array[i] != MPI_LB)	{	    if (!found_true_lb)	    {		found_true_lb = 1;		true_lb_disp  = tmp_true_lb;	    }	    else if (true_lb_disp > tmp_true_lb)	    {		/* element starts before previous */		true_lb_disp = tmp_true_lb;		definitely_not_contig = 1;	    }	    if (!found_true_ub)	    {		found_true_ub = 1;		true_ub_disp  = tmp_true_ub;	    }	    else if (true_ub_disp < tmp_true_ub)	    {		true_ub_disp = tmp_true_ub;	    }	    else {		/* element ends before previous ended */		definitely_not_contig = 1;	    }	}	if (!is_builtin && !old_dtp->is_contig)	{	    old_are_contig = 0;	}    }    new_dtp->n_elements = -1; /* TODO */    new_dtp->element_size = el_sz;    new_dtp->eltype = el_type;    new_dtp->has_sticky_lb = found_sticky_lb;    new_dtp->true_lb       = true_lb_disp;    new_dtp->lb = (found_sticky_lb) ? sticky_lb_disp : true_lb_disp;    new_dtp->has_sticky_ub = found_sticky_ub;    new_dtp->true_ub       = true_ub_disp;    new_dtp->ub = (found_sticky_ub) ? sticky_ub_disp : true_ub_disp;    new_dtp->alignsize = MPID_Type_struct_alignsize(count,						    oldtype_array,						    displacement_array);    new_dtp->extent = new_dtp->ub - new_dtp->lb;    if ((!found_sticky_lb) && (!found_sticky_ub))    {	/* account for padding */	MPI_Aint epsilon = (new_dtp->alignsize > 0) ?	    new_dtp->extent % new_dtp->alignsize : 0;	if (epsilon)	{	    new_dtp->ub    += (new_dtp->alignsize - epsilon);	    new_dtp->extent = new_dtp->ub - new_dtp->lb;	}    }    new_dtp->size = size;    /* new type is contig for N types if its size and extent are the     * same, and the old type was also contiguous, and we didn't see     * something noncontiguous based on true ub/ub.     */    if ((new_dtp->size == new_dtp->extent) && old_are_contig &&	(! definitely_not_contig))    {	new_dtp->is_contig = 1;    }    else    {	new_dtp->is_contig = 0;    }    *newtype = new_dtp->handle;    return mpi_errno;}

⌨️ 快捷键说明

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