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

📄 ad_read_coll.c

📁 MPICH是MPI的重要研究,提供了一系列的接口函数,为并行计算的实现提供了编程环境.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//*  *   $Id: ad_read_coll.c,v 1.17 2002/12/19 17:56:51 rross Exp $     * *   Copyright (C) 1997 University of Chicago.  *   See COPYRIGHT notice in top-level directory. */#include "adio.h"#include "adio_extern.h"#ifdef PROFILE#include "mpe.h"#endif/* prototypes of functions used for collective reads only. */static void ADIOI_Read_and_exch(ADIO_File fd, void *buf, MPI_Datatype				datatype, int nprocs,				int myrank, ADIOI_Access				*others_req, ADIO_Offset *offset_list,				int *len_list, int contig_access_count, 				ADIO_Offset				min_st_offset, ADIO_Offset fd_size,				ADIO_Offset *fd_start, ADIO_Offset *fd_end,				int *buf_idx, int *error_code);static void ADIOI_R_Exchange_data(ADIO_File fd, void *buf, ADIOI_Flatlist_node				  *flat_buf, ADIO_Offset *offset_list, int				  *len_list, int *send_size, int *recv_size,				  int *count, int *start_pos, 				  int *partial_send, 				  int *recd_from_proc, int nprocs, 				  int myrank, int				  buftype_is_contig, int contig_access_count,				  ADIO_Offset min_st_offset, 				  ADIO_Offset fd_size,				  ADIO_Offset *fd_start, ADIO_Offset *fd_end, 				  ADIOI_Access *others_req, 				  int iter, 				  MPI_Aint buftype_extent, int *buf_idx);static void ADIOI_Fill_user_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node				   *flat_buf, char **recv_buf, ADIO_Offset 				   *offset_list, int *len_list, 				   int *recv_size, 				   MPI_Request *requests, MPI_Status *statuses,				   int *recd_from_proc, int nprocs,				   int contig_access_count, 				   ADIO_Offset min_st_offset, 				   ADIO_Offset fd_size, ADIO_Offset *fd_start, 				   ADIO_Offset *fd_end,				   MPI_Aint buftype_extent);void ADIOI_GEN_ReadStridedColl(ADIO_File fd, void *buf, int count,			       MPI_Datatype datatype, int file_ptr_type,			       ADIO_Offset offset, ADIO_Status *status, int			       *error_code){/* Uses a generalized version of the extended two-phase method described   in "An Extended Two-Phase Method for Accessing Sections of    Out-of-Core Arrays", Rajeev Thakur and Alok Choudhary,   Scientific Programming, (5)4:301--317, Winter 1996.    http://www.mcs.anl.gov/home/thakur/ext2ph.ps */    ADIOI_Access *my_req;     /* array of nprocs structures, one for each other process in       whose file domain this process's request lies */        ADIOI_Access *others_req;    /* array of nprocs structures, one for each other process       whose request lies in this process's file domain. */    int i, filetype_is_contig, nprocs, nprocs_for_coll, myrank;    int *len_list, contig_access_count, interleave_count;    int *count_my_req_per_proc, count_my_req_procs, count_others_req_procs;    int buftype_is_contig, *buf_idx;    ADIO_Offset *offset_list, start_offset, end_offset, *st_offsets, orig_fp;    ADIO_Offset *fd_start, *fd_end, fd_size, min_st_offset, *end_offsets;    ADIO_Offset off;#ifdef HAVE_STATUS_SET_BYTES    int bufsize, size;#endif#ifdef PROFILE        MPE_Log_event(13, 0, "start computation");#endif    MPI_Comm_size(fd->comm, &nprocs);    MPI_Comm_rank(fd->comm, &myrank);    /* number of aggregators, cb_nodes, is stored in the hints */    nprocs_for_coll = fd->hints->cb_nodes;/* For this process's request, calculate the list of offsets and   lengths in the file and determine the start and end offsets. *//* Note: end_offset points to the last byte-offset that will be accessed.         e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/    orig_fp = fd->fp_ind;    ADIOI_Calc_my_off_len(fd, count, datatype, file_ptr_type, offset,			   &offset_list, &len_list, &start_offset,			   &end_offset, &contig_access_count);     /*    for (i=0; i<contig_access_count; i++) {	FPRINTF(stderr, "rank %d  off %ld  len %d\n", myrank, offset_list[i], 	        len_list[i]);    }*//* each process communicates its start and end offsets to other    processes. The result is an array each of start and end offsets stored   in order of process rank. */         st_offsets = (ADIO_Offset *) ADIOI_Malloc(nprocs*sizeof(ADIO_Offset));    end_offsets = (ADIO_Offset *) ADIOI_Malloc(nprocs*sizeof(ADIO_Offset));    MPI_Allgather(&start_offset, 1, ADIO_OFFSET, st_offsets, 1, ADIO_OFFSET, 		  fd->comm);    MPI_Allgather(&end_offset, 1, ADIO_OFFSET, end_offsets, 1, ADIO_OFFSET, 		  fd->comm);/* are the accesses of different processes interleaved? */    interleave_count = 0;    for (i=1; i<nprocs; i++)	if (st_offsets[i] < end_offsets[i-1]) interleave_count++;/* This is a rudimentary check for interleaving, but should suffice   for the moment. */    ADIOI_Datatype_iscontig(datatype, &buftype_is_contig);    if (fd->hints->cb_read == ADIOI_HINT_DISABLE	|| (!interleave_count && (fd->hints->cb_read == ADIOI_HINT_AUTO)))     {	/* don't do aggregation */	ADIOI_Free(offset_list);	ADIOI_Free(len_list);	ADIOI_Free(st_offsets);	ADIOI_Free(end_offsets);		fd->fp_ind = orig_fp;	ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig);	if (buftype_is_contig && filetype_is_contig) {	    if (file_ptr_type == ADIO_EXPLICIT_OFFSET) {		off = fd->disp + (fd->etype_size) * offset;		ADIO_ReadContig(fd, buf, count, datatype, ADIO_EXPLICIT_OFFSET,                       off, status, error_code);	    }	    else ADIO_ReadContig(fd, buf, count, datatype, ADIO_INDIVIDUAL,                       0, status, error_code);	}	else ADIO_ReadStrided(fd, buf, count, datatype, file_ptr_type,                       offset, status, error_code);	return;    }    /* We're going to perform aggregation of I/O.  Here we call     * ADIOI_Calc_file_domains() to determine what processes will handle I/O     * to what regions.  We pass nprocs_for_coll into this function; it is     * used to determine how many processes will perform I/O, which is also     * the number of regions into which the range of bytes must be divided.     * These regions are called "file domains", or FDs.     *     * When this function returns, fd_start, fd_end, fd_size, and     * min_st_offset will be filled in.  fd_start holds the starting byte     * location for each file domain.  fd_end holds the ending byte location.     * min_st_offset holds the minimum byte location that will be accessed.     *     * Both fd_start[] and fd_end[] are indexed by an aggregator number; this     * needs to be mapped to an actual rank in the communicator later.     *     */    ADIOI_Calc_file_domains(st_offsets, end_offsets, nprocs,			    nprocs_for_coll, &min_st_offset,			    &fd_start, &fd_end, &fd_size);    /* calculate where the portions of the access requests of this process      * are located in terms of the file domains.  this could be on the same     * process or on other processes.  this function fills in:     * count_my_req_procs - number of processes (including this one) for which     *     this process has requests in their file domain     * count_my_req_per_proc - count of requests for each process, indexed     *     by rank of the process     * my_req[] - array of data structures describing the requests to be     *     performed by each process (including self).  indexed by rank.     * buf_idx[] - array of locations into which data can be directly moved;     *     this is only valid for contiguous buffer case     */    ADIOI_Calc_my_req(fd, offset_list, len_list, contig_access_count,		      min_st_offset, fd_start, fd_end, fd_size,		      nprocs, &count_my_req_procs, 		      &count_my_req_per_proc, &my_req,		      &buf_idx);    /* perform a collective communication in order to distribute the     * data calculated above.  fills in the following:     * count_others_req_procs - number of processes (including this     *     one) which have requests in this process's file domain.     * count_others_req_per_proc[] - number of separate contiguous     *     requests from proc i lie in this process's file domain.     */    ADIOI_Calc_others_req(fd, count_my_req_procs, 			  count_my_req_per_proc, my_req, 			  nprocs, myrank, &count_others_req_procs, 			  &others_req);     /* my_req[] and count_my_req_per_proc aren't needed at this point, so      * let's free the memory      */    ADIOI_Free(count_my_req_per_proc);    for (i=0; i<nprocs; i++) {	if (my_req[i].count) {	    ADIOI_Free(my_req[i].offsets);	    ADIOI_Free(my_req[i].lens);	}    }    ADIOI_Free(my_req);    /* read data in sizes of no more than ADIOI_Coll_bufsize,      * communicate, and fill user buf.      */    ADIOI_Read_and_exch(fd, buf, datatype, nprocs, myrank,                        others_req, offset_list,			len_list, contig_access_count, min_st_offset,			fd_size, fd_start, fd_end, buf_idx, error_code);    if (!buftype_is_contig) ADIOI_Delete_flattened(datatype);    /* free all memory allocated for collective I/O */    for (i=0; i<nprocs; i++) {	if (others_req[i].count) {	    ADIOI_Free(others_req[i].offsets);	    ADIOI_Free(others_req[i].lens);	    ADIOI_Free(others_req[i].mem_ptrs);	}    }    ADIOI_Free(others_req);    ADIOI_Free(buf_idx);    ADIOI_Free(offset_list);    ADIOI_Free(len_list);    ADIOI_Free(st_offsets);    ADIOI_Free(end_offsets);    ADIOI_Free(fd_start);    ADIOI_Free(fd_end);#ifdef HAVE_STATUS_SET_BYTES    MPI_Type_size(datatype, &size);    bufsize = size * count;    MPIR_Status_set_bytes(status, datatype, bufsize);/* This is a temporary way of filling in status. The right way is to    keep track of how much data was actually read and placed in buf    during collective I/O. */#endif    fd->fp_sys_posn = -1;   /* set it to null. */}void ADIOI_Calc_my_off_len(ADIO_File fd, int bufcount, MPI_Datatype			    datatype, int file_ptr_type, ADIO_Offset			    offset, ADIO_Offset **offset_list_ptr, int			    **len_list_ptr, ADIO_Offset *start_offset_ptr,			    ADIO_Offset *end_offset_ptr, int			   *contig_access_count_ptr){    int filetype_size, buftype_size, etype_size;    int i, j, k, frd_size=0, old_frd_size=0, st_index=0;    int n_filetypes, etype_in_filetype;    ADIO_Offset abs_off_in_filetype=0;    int bufsize, sum, n_etypes_in_filetype, size_in_filetype;    int contig_access_count, *len_list, flag, filetype_is_contig;    MPI_Aint filetype_extent, filetype_lb;    ADIOI_Flatlist_node *flat_file;    ADIO_Offset *offset_list, off, end_offset=0, disp;    /* For this process's request, calculate the list of offsets and   lengths in the file and determine the start and end offsets. */    ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig);    MPI_Type_size(fd->filetype, &filetype_size);    MPI_Type_extent(fd->filetype, &filetype_extent);    MPI_Type_lb(fd->filetype, &filetype_lb);    MPI_Type_size(datatype, &buftype_size);    etype_size = fd->etype_size;    if ( ! filetype_size ) {	*contig_access_count_ptr = 0;	*offset_list_ptr = (ADIO_Offset *) ADIOI_Malloc(2*sizeof(ADIO_Offset));	*len_list_ptr = (int *) ADIOI_Malloc(2*sizeof(int));        /* 2 is for consistency. everywhere I malloc one more than needed */	offset_list = *offset_list_ptr;	len_list = *len_list_ptr;        offset_list[0] = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind :                  fd->disp + etype_size * offset;	len_list[0] = 0;	*start_offset_ptr = offset_list[0];	*end_offset_ptr = offset_list[0] + len_list[0] - 1;		return;    }    if (filetype_is_contig) {	*contig_access_count_ptr = 1;        	*offset_list_ptr = (ADIO_Offset *) ADIOI_Malloc(2*sizeof(ADIO_Offset));	*len_list_ptr = (int *) ADIOI_Malloc(2*sizeof(int));        /* 2 is for consistency. everywhere I malloc one more than needed */	offset_list = *offset_list_ptr;	len_list = *len_list_ptr;        offset_list[0] = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind :                  fd->disp + etype_size * offset;	len_list[0] = bufcount * buftype_size;	*start_offset_ptr = offset_list[0];	*end_offset_ptr = offset_list[0] + len_list[0] - 1;	/* update file pointer */	if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = *end_offset_ptr + 1;    }    else {       /* First calculate what size of offset_list and len_list to allocate */          /* filetype already flattened in ADIO_Open or ADIO_Fcntl */	flat_file = ADIOI_Flatlist;	while (flat_file->type != fd->filetype) flat_file = flat_file->next;	disp = fd->disp;	if (file_ptr_type == ADIO_INDIVIDUAL) {	    offset = fd->fp_ind; /* in bytes */	    n_filetypes = -1;	    flag = 0;	    while (!flag) {		n_filetypes++;		for (i=0; i<flat_file->count; i++) {		    if (disp + flat_file->indices[i] + 			(ADIO_Offset) n_filetypes*filetype_extent + 			flat_file->blocklens[i] >= offset) 

⌨️ 快捷键说明

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