📄 noncontig_coll2.c
字号:
/* -*- 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 + -