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