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

📄 cb_config_list.c

📁 MPICH是MPI的重要研究,提供了一系列的接口函数,为并行计算的实现提供了编程环境.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//*  *   $Id: cb_config_list.c,v 1.4 2002/10/24 17:01:14 gropp Exp $     * *   Copyright (C) 2001 University of Chicago.  *   See COPYRIGHT notice in top-level directory. *//* cb_config_list.c * * The important, externally used functions from this file are: * ADIOI_cb_bcast_rank_map() * ADIOI_cb_gather_name_array() * ADIOI_cb_config_list_parse() * ADIOI_cb_copy_name_array() * ADIOI_cb_delete_name_array() * * Prototypes for these are in adio/include/adio_cb_config_list.h */#include "adio.h"#include "mpi.h"#include "adio_cb_config_list.h"#include <stdio.h>#include <string.h>#include <stdlib.h>/* token types */#define AGG_WILDCARD 1#define AGG_STRING   2#define AGG_COMMA    3#define AGG_COLON    4#define AGG_ERROR   -1#define AGG_EOS      0#undef CB_CONFIG_LIST_DEBUG/* a couple of globals keep things simple */static int cb_config_list_keyval = MPI_KEYVAL_INVALID;static char *yylval;static char *token_ptr;/* internal stuff */static int get_max_procs(int cb_nodes);static int match_procs(char *name, int max_per_proc, char *procnames[], 		       char used_procnames[],		       int nr_procnames, int ranks[], int nr_ranks, 		       int *nr_ranks_allocated);static int match_this_proc(char *name, int cur_proc, int max_matches,			   char *procnames[], char used_procnames[],			   int nr_procnames, int ranks[], 			   int nr_ranks, int nr_ranks_allocated);static int find_name(char *name, char *procnames[], char used_procnames[], 		     int nr_procnames, int start_ind);static int cb_config_list_lex(void);/* ADIOI_cb_bcast_rank_map() - broadcast the rank array * * Parameters: * fd - ADIO_File for which update is occurring.  cb_nodes and ranklist * parameters must be up-to-date on rank 0 of the fd->comm. * * should probably be a void fn. */int ADIOI_cb_bcast_rank_map(ADIO_File fd){    int my_rank;    char *value;    MPI_Bcast(&(fd->hints->cb_nodes), 1, MPI_INT, 0, fd->comm);    if (fd->hints->cb_nodes > 0) {	MPI_Comm_rank(fd->comm, &my_rank);	if (my_rank != 0) {	    fd->hints->ranklist = ADIOI_Malloc(fd->hints->cb_nodes*sizeof(int));	    if (fd->hints->ranklist == NULL) {		/* NEED TO HANDLE ENOMEM */	    }	}	MPI_Bcast(fd->hints->ranklist, fd->hints->cb_nodes, MPI_INT, 0, 		  fd->comm);    }    /* TEMPORARY -- REMOVE WHEN NO LONGER UPDATING INFO FOR     * FS-INDEP. */    value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char));    sprintf(value, "%d", fd->hints->cb_nodes);    MPI_Info_set(fd->info, "cb_nodes", value);    ADIOI_Free(value);    return 0;}/* ADIOI_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 ADIOI_cb_gather_name_array(MPI_Comm comm,			       MPI_Comm dupcomm,			       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 *) ADIOI_cb_copy_name_array, 			  (MPI_Delete_function *) ADIOI_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(dupcomm, &commsize);    MPI_Comm_rank(dupcomm, &commrank);    MPI_Get_processor_name(my_procname, &my_procname_len);    /* allocate space for everything */    array = (ADIO_cb_name_array) ADIOI_Malloc(sizeof(*array));    if (array == NULL) {	return -1;    }    array->refct = 2; /* we're going to associate this with two comms */    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, dupcomm);    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] = ADIOI_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 = ADIOI_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, dupcomm);    }    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, dupcomm);    }    if (commrank == 0) {	/* no longer need the displacements or lengths */	ADIOI_Free(disp);	ADIOI_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.     *     * specifically we put it on both the original comm, so we can find     * it next time an open is performed on this same comm, and on the     * dupcomm, so we can use it in I/O operations.     */    MPI_Attr_put(comm, cb_config_list_keyval, array);    MPI_Attr_put(dupcomm, cb_config_list_keyval, array);    *arrayp = array;    return 0;}/* ADIOI_cb_config_list_parse() - parse the cb_config_list and build the  * ranklist * * Parameters: * (pretty self explanatory) * * Returns number of ranks allocated in parsing, -1 on error. */int ADIOI_cb_config_list_parse(char *config_list, 			 ADIO_cb_name_array array,			 int ranklist[], 			 int cb_nodes){    int token, max_procs, cur_rank = 0, nr_procnames;    char *cur_procname, *cur_procname_p, **procnames;    char *used_procnames;    nr_procnames = array->namect;    procnames = array->names;    /* nothing big goes on the stack */    /* we use info val here and for yylval because we know the string     * cannot be any bigger than this.     */    cur_procname = ADIOI_Malloc((MPI_MAX_INFO_VAL+1) * sizeof(char));    if (cur_procname == NULL) {	return -1;    }    yylval = ADIOI_Malloc((MPI_MAX_INFO_VAL+1) * sizeof(char));    if (yylval == NULL) {	ADIOI_Free(cur_procname);	return -1;    }    token_ptr = config_list;    /* right away let's make sure cb_nodes isn't too big */    if (cb_nodes > nr_procnames) cb_nodes = nr_procnames;    /* used_procnames is used as a mask so that we don't have to destroy     * our procnames array     */    used_procnames = ADIOI_Malloc(array->namect * sizeof(char));    if (used_procnames == NULL) {	ADIOI_Free(cur_procname);	ADIOI_Free(yylval);	yylval = NULL;	return -1;    }    memset(used_procnames, 0, array->namect);    /* optimization for "*:*"; arguably this could be done before we     * build the list of processor names...but that would make things     * messy.     */    if (strcmp(config_list, "*:*") == 0) {	for (cur_rank = 0; cur_rank < cb_nodes; cur_rank++) {	    ranklist[cur_rank] = cur_rank;	}	ADIOI_Free(cur_procname);	ADIOI_Free(yylval);	yylval = NULL;    	ADIOI_Free(used_procnames);	return cb_nodes;    }    while (cur_rank < cb_nodes) {	token = cb_config_list_lex();	if (token == AGG_EOS) {	    ADIOI_Free(cur_procname);	    ADIOI_Free(yylval);	    yylval = NULL;    	    ADIOI_Free(used_procnames);	    return cur_rank;	}	if (token != AGG_WILDCARD && token != AGG_STRING) {	    /* maybe ignore and try to keep going? */	    FPRINTF(stderr, "error parsing config list\n");	    ADIOI_Free(cur_procname);	    ADIOI_Free(yylval);	    yylval = NULL;    	    ADIOI_Free(used_procnames);	    return cur_rank;	}		if (token == AGG_WILDCARD) {	    cur_procname_p = NULL;	}	else {	    /* AGG_STRING is the only remaining case */	    /* save procname (for now) */	    strcpy(cur_procname, yylval);	    cur_procname_p = cur_procname;	}	/* after we have saved the current procname, we can grab max_procs */	max_procs = get_max_procs(cb_nodes);#ifdef CB_CONFIG_LIST_DEBUG	if (token == AGG_WILDCARD) {	    FPRINTF(stderr, "looking for *:%d\n", max_procs);	}	else {	    FPRINTF(stderr, "looking for %s:%d\n", cur_procname, max_procs);	}#endif	/* do the matching for this piece of the cb_config_list */	match_procs(cur_procname_p, max_procs, procnames, used_procnames,		    nr_procnames, ranklist, cb_nodes, &cur_rank);    }    ADIOI_Free(cur_procname);    ADIOI_Free(yylval);

⌨️ 快捷键说明

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