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

📄 noncontig_coll2.c

📁 mpi并行计算的c++代码 可用vc或gcc编译通过 可以用来搭建并行计算试验环境
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//*   *  (C) 2001 by Argonne National Laboratory. *      See COPYRIGHT in top-level directory. */#include "mpi.h"#include <stdio.h>#include <string.h>#include <stdlib.h>/* tests noncontiguous reads/writes using collective I/O *//* this test is almost exactly like noncontig_coll.c with the following changes: * * . generalized file writing/reading to handle arbitrary number of processors * . provides the "cb_config_list" hint with several permutations of the *   avaliable processors.   *   [ makes use of code copied from ROMIO's ADIO code to collect the names of *   the processors ] *//* we are going to muck with this later to make it evenly divisible by however many compute nodes we have */#define STARTING_SIZE 5000int test_file(char *filename, int mynod, int nprocs, char * cb_hosts, 		char *msg, int verbose); static int cb_config_list_keyval = MPI_KEYVAL_INVALID;#define ADIOI_Free free#define ADIOI_Malloc malloc#define FPRINTF fprintf/* I have no idea what the "D" stands for; it's how things are done in adio.h  */ struct ADIO_cb_name_arrayD {          int refct;                     int namect;       char **names;};  typedef struct ADIO_cb_name_arrayD *ADIO_cb_name_array;void handle_error(int errcode, char *str);int cb_copy_name_array(MPI_Comm comm, 		       int *keyval, 		       void *extra, 		       void *attr_in,		       void **attr_out, 		       int *flag);int cb_delete_name_array(MPI_Comm comm, 			 int *keyval, 			 void *attr_val, 			 void *extra);int cb_gather_name_array(MPI_Comm comm, ADIO_cb_name_array *arrayp);void default_str(int mynod, int len, ADIO_cb_name_array array, char *dest);void reverse_str(int mynod, int len, ADIO_cb_name_array array, char *dest);void reverse_alternating_str(int mynod, int len, ADIO_cb_name_array array, char *dest);void simple_shuffle_str(int mynod, int len, ADIO_cb_name_array array, char *dest);void handle_error(int errcode, char *str) {	char msg[MPI_MAX_ERROR_STRING];	int resultlen;	MPI_Error_string(errcode, msg, &resultlen);	fprintf(stderr, "%s: %s\n", str, msg);	MPI_Abort(MPI_COMM_WORLD, 1);} /* cb_copy_name_array() - attribute copy routine */int cb_copy_name_array(MPI_Comm comm, 		       int *keyval, 		       void *extra, 		       void *attr_in,		       void **attr_out, 		       int *flag){    ADIO_cb_name_array array;    array = (ADIO_cb_name_array) attr_in;    array->refct++;    *attr_out = attr_in;    *flag = 1; /* make a copy in the new communicator */        return MPI_SUCCESS;}/* cb_delete_name_array() - attribute destructor */int cb_delete_name_array(MPI_Comm comm, 			 int *keyval, 			 void *attr_val, 			 void *extra){    int i;    ADIO_cb_name_array array;    array = (ADIO_cb_name_array) attr_val;    array->refct--;    if (array->refct <= 0) {	/* time to free the structures (names, array of ptrs to names, struct) 	 */	for (i=0; i < array->namect; i++) {	    ADIOI_Free(array->names[i]);	}	if (array->names != NULL) ADIOI_Free(array->names);	ADIOI_Free(array);    }    return MPI_SUCCESS;}   /* cb_gather_name_array() - gather a list of processor names from all processes *                          in a communicator and store them on rank 0. *                    * This is a collective call on the communicator(s) passed in. * * Obtains a rank-ordered list of processor names from the processes in * "dupcomm". * * Returns 0 on success, -1 on failure. *  * NOTE: Needs some work to cleanly handle out of memory cases!   */int cb_gather_name_array(MPI_Comm comm, ADIO_cb_name_array *arrayp){    char my_procname[MPI_MAX_PROCESSOR_NAME], **procname = 0;    int *procname_len = NULL, my_procname_len, *disp = NULL, i;    int commsize, commrank, found;    ADIO_cb_name_array array = NULL;    if (cb_config_list_keyval == MPI_KEYVAL_INVALID) {	MPI_Keyval_create((MPI_Copy_function *) cb_copy_name_array, 			  (MPI_Delete_function *) cb_delete_name_array,			  &cb_config_list_keyval, NULL);    }    else {	MPI_Attr_get(comm, cb_config_list_keyval, (void *) &array, &found);	if (found) {	    *arrayp = array;	    return 0;	}    }    MPI_Comm_size(comm, &commsize);    MPI_Comm_rank(comm, &commrank);    MPI_Get_processor_name(my_procname, &my_procname_len);    /* allocate space for everything */    array = (ADIO_cb_name_array) malloc(sizeof(*array));    if (array == NULL) {	return -1;    }    array->refct = 1;     if (commrank == 0) {	/* process 0 keeps the real list */	array->namect = commsize;	array->names = (char **) ADIOI_Malloc(sizeof(char *) * commsize);	if (array->names == NULL) {	    return -1;	}	procname = array->names; /* simpler to read */	procname_len = (int *) ADIOI_Malloc(commsize * sizeof(int));	if (procname_len == NULL) { 	    return -1;	}    }    else {	/* everyone else just keeps an empty list as a placeholder */	array->namect = 0;	array->names = NULL;    }    /* gather lengths first */    MPI_Gather(&my_procname_len, 1, MPI_INT, 	       procname_len, 1, MPI_INT, 0, comm);    if (commrank == 0) {#ifdef CB_CONFIG_LIST_DEBUG	for (i=0; i < commsize; i++) {	    FPRINTF(stderr, "len[%d] = %d\n", i, procname_len[i]);	}#endif	for (i=0; i < commsize; i++) {	    /* add one to the lengths because we need to count the	     * terminator, and we are going to use this list of lengths	     * again in the gatherv.  	     */	    procname_len[i]++;	    procname[i] = malloc(procname_len[i]);	    if (procname[i] == NULL) {		return -1;	    }	}		/* create our list of displacements for the gatherv.  we're going	 * to do everything relative to the start of the region allocated	 * for procname[0]	 *	 * I suppose it is theoretically possible that the distance between 	 * malloc'd regions could be more than will fit in an int.  We don't	 * cover that case.	 */	disp = malloc(commsize * sizeof(int));	disp[0] = 0;	for (i=1; i < commsize; i++) {	    disp[i] = (int) (procname[i] - procname[0]);	}    }    /* now gather strings */    if (commrank == 0) {	MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR, 		    procname[0], procname_len, disp, MPI_CHAR,		    0, comm);    }    else {	/* if we didn't do this, we would need to allocate procname[]	 * on all processes...which seems a little silly.	 */	MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR, 		    NULL, NULL, NULL, MPI_CHAR, 0, comm);    }    if (commrank == 0) {	/* no longer need the displacements or lengths */	free(disp);	free(procname_len);#ifdef CB_CONFIG_LIST_DEBUG	for (i=0; i < commsize; i++) {	    fprintf(stderr, "name[%d] = %s\n", i, procname[i]);	}#endif    }    /* store the attribute; we want to store SOMETHING on all processes     * so that they can all tell if we have gone through this procedure      * or not for the given communicator.     */    MPI_Attr_put(comm, cb_config_list_keyval, array);    *arrayp = array;    return 0;}void default_str(int mynod, int len, ADIO_cb_name_array array, char *dest){	char *ptr;	int i, p;	if (!mynod) {	    ptr = dest;	    for (i=0; i<array->namect; i++ ) {		    p = snprintf(ptr, len, "%s,", array->names[i]);		    ptr += p;	    }	    /* chop off that last comma */	    dest[strlen(dest) - 1] = '\0';	}	MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);}void reverse_str(int mynod, int len, ADIO_cb_name_array array, char *dest) {	char *ptr;	int i, p;	if (!mynod) {	    ptr = dest;	    for (i=(array->namect - 1); i >= 0; i-- ) {		    p = snprintf(ptr, len, "%s,", array->names[i]);		    ptr += p;	    }	    dest[strlen(dest) - 1] = '\0';	}	MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);}void reverse_alternating_str(int mynod, int len, ADIO_cb_name_array array, char *dest){	char *ptr;	int i, p;	if (!mynod) {	    ptr = dest;	    /* evens */	    for (i=(array->namect - 1); i>= 0; i-=2 ) {		    p = snprintf(ptr, len, "%s,", array->names[i]);		    ptr += p;	    }	    /* odds */	    for (i=(array->namect - 2); i > 0; i-=2 ) {		    p = snprintf(ptr, len, "%s,", array->names[i]);		    ptr += p;	    }

⌨️ 快捷键说明

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