Michael J. Quinn, 《Parallel Programming in C with MPI and OpenMP》程序代码
来源:互联网 发布:股票预测算法 编辑:程序博客网 时间:2024/06/08 06:07
本文中是Michael J. Quinn在书《Parallel Programming in C with MPI and OpenMP》(中文《MPI与OpenMP并行程序设计:C语言版》,陈文光、武永卫等译)中所使用的MyMPI.h和MyMPI.c文件. 有小部分细节上的调整,并经过测试可用.
MyMPI.h
/* MyMPI.h * * Header file for a library of matrix/vector * input/output/redistribution functions. * * Programed by Michael J. Quinn * Last modification: 4 September 2002 * "Parallel Programming in C with MPI and OpenMP" * Typed and modified by xiu_dim, 17 Nov. 2015 *//******************** MACROS *********************/#define DATA_MSG 0#define PROMPT_MSG 1#define RESPONSE_MSG 2#define OPEN_FILE_ERROR -1#define MALLOC_ERROR -2#define TYPE_ERROR -3#define PTR_SIZE (sizeof(void *))#define MIN(a,b) ((a)<(b)?(a):(b))#define CEILING(i,j) (((i)+(j)-1)/(j))#define BLOCK_LOW(id,p,n) ((id)*(n)/(p))#define BLOCK_HIGH(id,p,n) (BLOCK_LOW((id)+1,p,n)-1)#define BLOCK_SIZE(id,p,n) \ (BLOCK_HIGH(id,p,n)-BLOCK_LOW(id,p,n)+1)#define BLOCK_OWNER(j,p,n) (((p)*((j)+1)-1)/(n))/************ MISCELLANEOUS FUNCTIONS ************/int get_size(MPI_Datatype);void* my_malloc(int, int);void terminate(int, char*);/********** DATA DISTRIBUTION FUNCTIONS **********/void create_mixed_xfer_arrays(int, int, int, int**, int**);void create_uniform_xfer_arrays(int, int, int, int**, int**);void replicate_block_vector(void*, int, void*, MPI_Datatype, MPI_Comm);/**************** INPUT FUNCTIONS ****************/void read_row_striped_matrix(char*, void***, void**, MPI_Datatype, int*, int*, MPI_Comm);void read_col_striped_matrix(char*, void***, void**, MPI_Datatype, int*, int*, MPI_Comm);void read_checkerboard_matrix(char*, void***, void**, MPI_Datatype, int*, int*, MPI_Comm);void read_block_vector(char*, void**, MPI_Datatype, int*, MPI_Comm);void read_replicated_vector(char*, void**, MPI_Datatype, int*, MPI_Comm);/**************** OUTPUT FUNCTIONS ***************/void print_submatrix(void**, MPI_Datatype, int, int);void print_subvector(void*, MPI_Datatype, int);void print_row_striped_matrix(void**, MPI_Datatype, int, int, MPI_Comm);void print_col_striped_matrix(void**, MPI_Datatype, int, int, MPI_Comm);void print_checkerboard_matrix(void**, MPI_Datatype, int, int, MPI_Comm);void print_block_vector(void*, MPI_Datatype, int, MPI_Comm);void print_replicated_vector(void*, MPI_Datatype, int, MPI_Comm);
MyMPI.c
/* MyMPI.c -- A library of matrix/vector * input/output/redistribution functions. * * Programed by Michael J. Quinn * Last modification: 4 September 2002 * "Parallel Programming in C with MPI and OpenMP" * Typed and modified by xiu_dim, 17 Nov. 2015 */#include <mpi.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "MyMPI.h"/************ MISCELLANEOUS FUNCTIONS ************//* * Given MPI_DataType 't', function 'get_size' returns the * size of a single datum that data type. */int get_size(MPI_Datatype t){ if (t == MPI_BYTE) return sizeof(char); if (t == MPI_DOUBLE) return sizeof(double); if (t == MPI_FLOAT) return sizeof(float); if (t == MPI_INT) return sizeof(int); printf("Error: Unrecognized argument to 'get_size'\n"); fflush(stdout); MPI_Abort(MPI_COMM_WORLD, TYPE_ERROR);}/* * Function 'my_malloc' is called when a process wants * to allocate some space from the heap. If the memory * allocation fails, the process prints an error message * and then aborts execution of the program. */void *my_malloc( int id, /* IN - Process rank */ int bytes) /* IN - Bytes to allocate */{ void *buffer; if ((buffer = malloc((size_t)bytes)) == NULL) { printf("Error:Malloc failed for process %d\n", id); fflush(stdout); MPI_Abort(MPI_COMM_WORLD, MALLOC_ERROR); } return buffer;}/* * Function 'terminate' is called when the program should * not continue execution, due to an error conditon that * all of the processes are aware of. Process 0 prints the * error message passed as an argument to the function. * * All processes must invoke this function together! */void terminate( int id, /* IN - Process rank */ char *error_message) /* IN - Message to print */{ if (!id) { printf("Error: %s\n", error_message); fflush(stdout); } MPI_Finalize(); exit(-1);}/********** DATA DISTRIBUTION FUNCTIONS **********//* * This function creates the count and displacement arrays * needed by scatter and gather functions, when the number * of elements send/received to/from other processes varies. */void create_mixed_xfer_arrays( int id, /* IN - Process rank */ int p, /* IN - Number of processes */ int n, /* IN - Total number of elements */ int **count, /* OUT - Array of counts */ int **disp) /* OUT - Array of displacements */{ int i; *count = my_malloc(id, p*sizeof(int)); *disp = my_malloc(id, p*sizeof(int)); (*count)[0] = BLOCK_SIZE(0,p,n); (*disp)[0] = 0; for (i=1; i<p; ++i) { (*disp)[i] = (*disp)[i-1] + (*count)[i-1]; (*count)[i] = BLOCK_SIZE(i,p,n); } return;}/* * This function creates the count and displacement arrays * needed in an all-to-all exchange, when a process gets * the same number of elements from every other process. */void create_uniform_xfer_arrays( int id, /* IN - Process rank */ int p, /* IN - Number of processes */ int n, /* IN - Total number of elements */ int **count, /* OUT - Array of counts */ int **disp) /* OUT - Array of displacements */{ int i; *count = my_malloc(id, p*sizeof(int)); *disp = my_malloc(id, p*sizeof(int)); (*count)[0] = BLOCK_SIZE(id,p,n); (*disp)[0] = 0; for (i=1; i<p; ++i) { (*disp)[i] = (*disp)[i-1] + (*count)[i-1]; (*count)[i] = BLOCK_SIZE(id,p,n); } return;}/* * This function is used to transform a vector from a * block distribution to a replicated distribution within * a communicator. */void replicate_block_vector( void *ablock, /* IN - Block-distributed vector */ int n, /* IN - Number of elements in vector */ void *arep, /* OUT - Replicated vector */ MPI_Datatype dtype, /* IN - Vector element type */ MPI_Comm comm) /* IN - Communicator */{ int p; /* Number of processes */ int id; /* Process rank */ int *cnt; /* Number of elements contributed by each process */ int *disp; /* Displacement in concatenated array */ MPI_Comm_size(comm, &p); MPI_Comm_rank(comm, &id); create_mixed_xfer_arrays(id, p, n, &cnt, &disp); MPI_Allgatherv(ablock, cnt[id], dtype, arep, cnt, disp, dtype, comm); free(cnt); free(disp); return;}/**************** INPUT FUNCTIONS ****************//* * In the matrix file, the first two elemnts are * integers whose values are the dimensions of the * matrix ('m' rows and 'n' columns). What follows * are 'm'*'n' values representing the matrix elements * stored in row-major order. *//* * Process p-1 opens a file and inputs a two-dimensional * matrix, reading and distributing blocks of rows to the * other MPI processes. */void read_row_striped_matrix( char *s, /* IN - File name */ void ***subs, /* OUT - Submatrix row indices */ void **storage, /* OUT - Submatrix stored here */ MPI_Datatype dtype, /* IN - Matrix element type */ int *m, /* OUT - Number of rows in matrix */ int *n, /* OUT - Number of cols in matrix */ MPI_Comm comm) /* IN - Communicator */{ int p; /* Number of processes */ int id; /* Process rank */ int datum_size; /* Size of matrix element */ int local_rows; /* Number of rows in this process */ FILE *infileptr; /* Input file poiter */ void **lptr; /* Pointer into 'subs' */ void *rptr; /* Pointer into 'storage' */ MPI_Status status; /* Result of receive */ int x; /* Result of read */ int i; MPI_Comm_size(comm, &p); MPI_Comm_rank(comm, &id); datum_size = get_size(dtype); /* Process p-1 opens the file 's' */ if (id == p-1) { infileptr = fopen(s, "r"); if (infileptr == NULL) *m = 0; else { x = fread(m, sizeof(int), 1, infileptr); x = fread(n, sizeof(int), 1, infileptr); } } /* Process p-1 broadcasts 'm' in communicator 'comm' */ MPI_Bcast(m, 1, MPI_INT, p-1, comm); if (!(*m)) MPI_Abort(MPI_COMM_WORLD, OPEN_FILE_ERROR); /* Process p-1 broadcasts 'n' in communicator 'comm' */ MPI_Bcast(n, 1, MPI_INT, p-1, comm); /* Number of rows in this process */ local_rows = BLOCK_SIZE(id,p,*m); /* Allocate array for submatrix in this process */ *storage = (void *)my_malloc(id, local_rows*(*n)*datum_size); /* Allocate array for row indices in this pointers */ *subs = (void **)my_malloc(id, local_rows*PTR_SIZE); /* Connet 'subs' with 'storage' */ lptr = (void *)&(*subs[0]); rptr = (void *)*storage; for (i=0; i<local_rows; ++i) { *(lptr++) = (void *)rptr; rptr += (*n) * datum_size; } if (id == (p-1)) { for (i=0; i<p-1; ++i) { /* Process p-1 reads datum from 'infileptr' and sends it together with tag 'DATA_MSG' to process i in communicator 'comm' */ x = fread(*storage, datum_size, BLOCK_SIZE(i,p,*m)*(*n), infileptr); MPI_Send(*storage, BLOCK_SIZE(i,p,*m)*(*n), dtype, i, DATA_MSG, comm); } /* Process p-1 reads datum from 'infileptr' */ x = fread(*storage, datum_size, BLOCK_SIZE(i,p,*m)*(*n), infileptr); fclose(infileptr); } else /* This process receives datum from process p-1 */ MPI_Recv(*storage, local_rows*(*n), dtype, p-1, DATA_MSG, comm, &status); return;}/* * Process p-1 opens a file and inputs a two-dimensional * matrix, reading and distributing blocks of columns to * the other MPI processes. */void read_col_striped_matrix( char *s, /* IN - File name */ void ***subs, /* OUT - 2-D array */ void **storage, /* OUT - Array elements */ MPI_Datatype dtype, /* IN - Matrix element type */ int *m, /* OUT - Number of rows in matrix */ int *n, /* OUT - Number of cols in matrix */ MPI_Comm comm) /* IN - Communicator */{ int p; /* Number of processes */ int id; /* Process rank */ int datum_size; /* Size of matrix element */ int local_cols; /* Number of cols in this process */ FILE *infileptr; /* Input file poiter */ void *buffer; /* File buffer */ void **lptr; /* Pointer into 'subs' */ void *rptr; /* Pointer into 'storage' */ int *send_count; /* Each process's count */ int *send_disp; /* Each process's displacement */ int i,j; MPI_Comm_size(comm, &p); MPI_Comm_rank(comm, &id); datum_size = get_size(dtype); /* Process p-1 opens the file 's' */ if (id == (p-1)) { infileptr = fopen(s, "r"); if (infileptr == NULL) *m = 0; else { fread(m, sizeof(int), 1, infileptr); fread(n, sizeof(int), 1, infileptr); } } /* Process p-1 broadcasts 'm' in communicator 'comm' */ MPI_Bcast(m, 1, MPI_INT, p-1, comm); if (!(*m)) MPI_Abort(comm, OPEN_FILE_ERROR); /* Process p-1 broadcasts 'n' in communicator 'comm' */ MPI_Bcast(n, 1, MPI_INT, p-1, comm); /* Number of cols in this process */ local_cols = BLOCK_SIZE(id,p,*n); /* Dynamically allocate two-dimensional matrix 'subs' */ /* Allocate array for submatrix in this process */ *storage = my_malloc(id, (*m)*local_cols*datum_size); /* Allocate array for row indices in this pointers */ *subs = (void **)my_malloc(id, (*m)*PTR_SIZE); lptr = (void *)*subs; rptr = (void *)*storage; for (i=0; i<(*m); ++i) { *(lptr++) = (void *)rptr; rptr += local_cols * datum_size; } if (id == (p-1)) buffer = my_malloc(id, (*n)*datum_size); create_mixed_xfer_arrays(id, p, *n, &send_count, &send_disp); for (i=0; i<(*m); ++i) { if (id == (p-1)) fread(buffer, datum_size, *n, infileptr); MPI_Scatterv(buffer, send_count, send_disp, dtype, (*storage)+i*local_cols*datum_size, local_cols, dtype, p-1, comm); } free(send_count); free(send_disp); if (id == (p-1)) free(buffer); return;}/* * This function allocate blocks of the matrix to * the MPI processes. * * The number of processes MUST be a square number. */void read_checkerboard_matrix( char *s, /* IN - File name */ void ***subs, /* OUT - 2-D array */ void **storage, /* OUT - Array elements */ MPI_Datatype dtype, /* IN - Matrix element type */ int *m, /* OUT - Number of rows in matrix */ int *n, /* OUT - Number of cols in matrix */ MPI_Comm grid_comm) /* IN - Communicator */{ int p; /* Number of processes */ int grid_id; /* Process rank in grid */ int datum_size; /* Size of matrix element */ int coords[2]; /* Coords of process receiving next row of matrix */ int grid_coords[2]; /* Coords of this process */ int grid_period[2]; /* Wraparound */ int grid_size[2]; /* Dimemsions of process grid */ int local_rows; /* Number of matrix rows in this process */ int local_cols; /* Number of matrix cols in this process */ FILE *infileptr; /* Input file poiter */ void *buffer; /* File buffer */ void **lptr; /* Pointer into 'subs' */ void *rptr; /* Pointer into 'storage' */ void *laddr; /* Used when process 0 gets row */ void *raddr; /* Address of first element to send */ int dest_id; /* Rank of receiving process */ MPI_Status status; /* Result of receive */ int i,j,k; MPI_Comm_size(grid_comm, &p); MPI_Comm_rank(grid_comm, &grid_id); datum_size = get_size(dtype); /* Process 0 opens file, get numbers of rows and cols, and broadcasts this information to the other processes */ if (grid_id == 0) { infileptr = fopen(s, "r"); if (infileptr == NULL) *m = 0; else { fread(m, sizeof(int), 1, infileptr); fread(n, sizeof(int), 1, infileptr); } } MPI_Bcast(m, 1, MPI_INT, 0, grid_comm); if (!(*m)) MPI_Abort(MPI_COMM_WORLD, OPEN_FILE_ERROR); MPI_Bcast(n, 1, MPI_INT, 0, grid_comm); /* Each process determines the size of the submatrix it is responsible for. */ MPI_Cart_get(grid_comm, 2, grid_size, grid_period, grid_coords); local_rows = BLOCK_SIZE(grid_coords[0],grid_size[0],*m); local_cols = BLOCK_SIZE(grid_coords[1],grid_size[1],*n); /* Dynamicaly allocate two-dimensional matrix 'subs' */ *storage = my_malloc(grid_id, local_rows*local_cols*datum_size); *subs = (void **)my_malloc(grid_id, local_rows*PTR_SIZE); lptr = (void *)*subs; rptr = (void *)*storage; for (i=0; i<local_rows; ++i) { *(lptr++) = (void *)rptr; rptr += local_cols * datum_size; } /* Grid process 0 reads in the matrix one row at a time and distributes each row among the MPI processes */ if (grid_id == 0) buffer = my_malloc(grid_id, (*n)*datum_size); /* For each row of processes in the process grid */ for (i=0; i<grid_size[0]; ++i) { coords[0] = i; /* For each matrix row controlled by this process row */ for (j=0; j<BLOCK_SIZE(i,grid_size[0],*m); ++j) { /* Read in a row of the matrix */ if (grid_id == 0) { fread(buffer, datum_size, *n, infileptr); } /* Distribute it among processes in the grid row */ for (k=0; k<grid_size[1]; ++k) { coords[1] = k; /* Find address of first element to send */ raddr = buffer + BLOCK_LOW(k,grid_size[1],*n) * datum_size; /* Determine the grid ID of the process getting the subrow */ MPI_Cart_rank(grid_comm, coords, &dest_id); if (grid_id == 0) { /* Process 0 is responsible for sending */ if (dest_id == 0) { /* It is sending(copying) to itself */ laddr = (*subs)[j]; memcpy(laddr, raddr, local_cols*datum_size); } else { /* It is sending to another process */ MPI_Send(raddr, BLOCK_SIZE(k,grid_size[1],*n), dtype, dest_id, 0, grid_comm); } } else if (grid_id == dest_id) { /* Process 'dest_id' is responsible for receiving */ MPI_Recv((*subs)[j], local_cols, dtype, 0, 0, grid_comm, &status); } } } } if (grid_id == 0) free(buffer); return;}/* * Process p-1 opens a file containing a vector, reads * its contents, and distributes the elements by block * among the processes in a communicator. */void read_block_vector( char *s, /* IN - File name */ void **v, /* OUT - Subvector */ MPI_Datatype dtype, /* IN - Vector element type */ int *n, /* OUT - Vector length */ MPI_Comm comm) /* IN - Communicator */{ int p; /* Number of processes */ int id; /* Process rank */ int datum_size; /* Size of vector element */ int local_els; /* Number of elements in this process */ FILE *infileptr; /* Input file poiter */ MPI_Status status; /* Result of receive */ int x; /* Result of read */ int i; MPI_Comm_size(comm,&p); MPI_Comm_rank(comm, &id); datum_size = get_size(dtype); /* Process p-1 opens file, determines number of vector elements, and broadcasts this value to the other processes */ if (id == (p-1)) { infileptr = fopen(s, "r"); if (infileptr == NULL) *n = 0; else fread(n, sizeof(int), 1, infileptr); } MPI_Bcast(n, 1, MPI_INT, p-1, comm); if (!(*n)) { if (!id) { printf("Input file '%s' cannot be opened\n", s); fflush(stdout); } } /* Block mapping of vetor elements to processes */ local_els = BLOCK_SIZE(id,p,*n); *v = my_malloc(id, local_els*datum_size); if (id == (p-1)) { for (i=0; i<p-1; ++i) { x = fread(*v, datum_size, BLOCK_SIZE(i,p,*n), infileptr); MPI_Send(*v, BLOCK_SIZE(i,p,*n), dtype, i, DATA_MSG, comm); } x = fread(*v, datum_size, BLOCK_SIZE(id,p,*n), infileptr); fclose(infileptr); } else { MPI_Recv(*v, BLOCK_SIZE(id,p,*n), dtype, p-1, DATA_MSG, comm, &status); } return;}/* * Process p-1 opens a file containing a vector, reads its * contents, and replicates the vector among all processes * in a communicator. */void read_replicated_vector( char *s, /* IN - File name */ void **v, /* OUT - Subvector */ MPI_Datatype dtype, /* IN - Vector element type */ int *n, /* OUT - Vector length */ MPI_Comm comm) /* IN - Communicator */{ int p; /* Number of processes */ int id; /* Process rank */ int datum_size; /* Size of vector element */ FILE *infileptr; /* Input file poiter */ int i; /* Process p-1 opens file, determines number of vector elements, and broadcasts this value to the other processes */ MPI_Comm_size(comm, &p); MPI_Comm_rank(comm, &id); datum_size = get_size(dtype); if (id == (p-1)) { infileptr = fopen(s, "r"); if (infileptr == NULL) *n = 0; else fread(n, sizeof(int), 1, infileptr); } MPI_Bcast(n, 1, MPI_INT, p-1, comm); if (!(*n)) terminate(id, "Cannot open vector file!"); *v = my_malloc(id, (*n)*datum_size); if (id == (p-1)) { fread(*v, datum_size, *n, infileptr); fclose(infileptr); } MPI_Bcast(*v, *n, dtype, p-1, MPI_COMM_WORLD); return;}/**************** OUTPUT FUNCTIONS ***************//* * Print elements of a doubly subscripted array. */void print_submatrix( void **a, /* IN - Doubly subscripted array */ MPI_Datatype dtype, /* IN - Type of element */ int rows, /* IN - Number of rows */ int cols) /* IN - Number of columns */{ int i,j; for (i=0; i<rows; ++i) { for (j=0; j<cols; ++j) { if (dtype == MPI_DOUBLE) printf("%6.3f",((double **)a)[i][j]); else { if (dtype == MPI_FLOAT) printf("%6.3f",((float **)a)[i][j]); else printf("%6d",((int **)a)[i][j]); } } putchar('\n'); } return;}/* * Print elements of a singly subscripted array. */void print_subvector( void *a, /* IN - Singly subscripted array */ MPI_Datatype dtype, /* IN - Type of elements */ int n) /* IN - Size of array */{ int i; for (i=0; i<n; ++i) { if (dtype == MPI_DOUBLE) printf("%6.3f ",((double *)a)[i]); else { if (dtype == MPI_FLOAT) printf("%6.3f ",((float *)a)[i]); else if (dtype == MPI_INT) printf("%6d ",((int *)a)[i]); } } return;}/* * Process 0 prints a matrix that is distributed in row- * striped fashion among the processes in a communicator. */void print_row_striped_matrix( void **a, /* IN - 2D array */ MPI_Datatype dtype, /* IN - Matrix element type */ int m, /* IN - Number of matrix rows */ int n, /* IN - Number of matrix columns */ MPI_Comm comm) /* IN - Communicator */{ int p; /* Number of processes */ int id; /* Process rank */ int datum_size; /* Size of matrix element */ int local_rows; /* Rows in this process */ int max_block_size; /* Most matrix rows held by any process */ void *bstorage; /* Elements received from another process */ void **b; /* 2D array indexing into 'bstorage' */ MPI_Status status; /* Result of receive */ int prompt; /* Dummy variable */ int i; MPI_Comm_size(comm, &p); MPI_Comm_rank(comm, &id); datum_size = get_size(dtype); local_rows = BLOCK_SIZE(id,p,n); if (!id) { print_submatrix(a, dtype, local_rows, n); if (p >1) { max_block_size = BLOCK_SIZE(p-1,p,m); bstorage = (void *)my_malloc(id, max_block_size*n*datum_size); b = (void **)my_malloc(id, max_block_size*PTR_SIZE); b[0] = bstorage; for (i=1; i<max_block_size; ++i) { b[i] = b[i-1] + n * datum_size; } for (i=1; i<p; ++i) { /* Send a prompt message to process i in the default communicator */ MPI_Send(&prompt, 1, MPI_INT, i, PROMPT_MSG, MPI_COMM_WORLD); /* Receive datum with tag 'RESPONSE_MSG' from process i in the default communicator */ MPI_Recv(bstorage, BLOCK_SIZE(i,p,m)*n, dtype, i, RESPONSE_MSG, MPI_COMM_WORLD, &status); print_submatrix(b, dtype, BLOCK_SIZE(i,p,m), n); } free(b); free(bstorage); } putchar('\n'); } else { /* Receive a prompt message from process 0 in the default communicator */ MPI_Recv(&prompt, 1, MPI_INT, 0, PROMPT_MSG, MPI_COMM_WORLD,&status); /* Send datum with tag 'RESPONSE_MSG' to process 0 in the default communicator */ MPI_Send(*a, local_rows*n, dtype, 0, RESPONSE_MSG, MPI_COMM_WORLD); } return;}/* * Process 0 prints a matrix that has a * columnwise-block-striped data decompsition * among the processes in a communicator. */void print_col_striped_matrix( void **a, /* IN - 2D array */ MPI_Datatype dtype, /* IN - Matrix element type */ int m, /* IN - Number of matrix rows */ int n, /* IN - Number of matrix columns */ MPI_Comm comm) /* IN - Communicator */{ int p; /* Number of processes */ int id; /* Process rank */ int datum_size; /* Size of matrix element */ void *buffer; /* Buffer to hold one row */ int *rec_count; /* Number of elements received per process */ int *rec_disp; /* Offset of each process's block */ MPI_Status status; /* Result of receive */ int i,j; MPI_Comm_size(comm, &p); MPI_Comm_rank(comm, &id); datum_size = get_size(dtype); create_mixed_xfer_arrays(id, p, n, &rec_count, &rec_disp); if (!id) buffer = my_malloc(id, n*datum_size); for (i=0; i<m; ++i) { MPI_Gatherv(a[i], BLOCK_SIZE(id,p,n), dtype, buffer, rec_count, rec_disp, dtype, 0, MPI_COMM_WORLD); if (!id) { print_subvector(buffer, dtype, n); putchar('\n'); } } free(rec_count); free(rec_disp); if (!id) { free(buffer); putchar('n'); } return;}/* * This function prints a matrix distributed checkerboard * fashion among the processes in a communicator. */void print_checkerboard_matrix( void **a, /* IN - 2D array */ MPI_Datatype dtype, /* IN - Matrix element type */ int m, /* IN - Number of matrix rows */ int n, /* IN - Number of matrix columns */ MPI_Comm grid_comm) /* IN - Communicator */{ int p; /* Number of processes */ int grid_id; /* Process rank in grid */ int datum_size; /* Size of matrix element */ int coords[2]; /* Grid coords of process sending elements */ int grid_coords[2]; /* Coords of this process */ int grid_period[2]; /* Wraparound */ int grid_size[2]; /* Dimemsions of process grid */ int local_cols; /* Number of matrix cols in this process */ int els; /* Element received */ int src; /* ID of process with subrow */ void *buffer; /* Buffer to hold one matrix row */ void *laddr; /* Address to put subrow */ MPI_Status status; /* Result of receive */ int i,j,k; MPI_Comm_size(grid_comm, &p); MPI_Comm_rank(grid_comm, &grid_id); datum_size = get_size(dtype); MPI_Cart_get(grid_comm, 2, grid_size, grid_period, grid_coords); local_cols = BLOCK_SIZE(grid_coords[1],grid_size[1],n); if (!grid_id) buffer = my_malloc(grid_id, n*datum_size); /* For each row of the process grid */ for (i=0; i<grid_size[0]; ++i) { coords[0] = i; /* For each matrix row controlled by the process row*/ for (j=0; j<BLOCK_SIZE(i,grid_size[0],m); ++j) { /* Collect the matrix row on grid process 0 and print it */ if (!grid_id) { for (k=0; k<grid_size[1]; ++k) { coords[1] = k; MPI_Cart_rank(grid_comm, coords, &src); els = BLOCK_SIZE(k,grid_size[1],n); laddr = buffer + BLOCK_LOW(k,grid_size[1],n) * datum_size; if (src == 0) { memcpy(laddr, a[j], els*datum_size); } else { MPI_Recv(laddr, els, dtype, src, 0, grid_comm, &status); } } print_subvector(buffer, dtype, n); putchar('\n'); } else if (grid_coords[0] == i) { MPI_Send(a[j], local_cols, dtype, 0, 0, grid_comm); } } } if (!grid_id) { free(buffer); putchar('\n'); } return;}/* * Process 0 prints a vector that is block distributed * among the processes in a communicator. */void print_block_vector( void *v, /* IN - Address of vector */ MPI_Datatype dtype, /* IN - Vector element type */ int n, /* IN - Vector length */ MPI_Comm comm) /* IN - Communicator */{ int p; /* Number of processes */ int id; /* Process rank */ int datum_size; /* Size of vector element */ void *tmp; /* Other process's subvector */ MPI_Status status; /* Result of receive */ int prompt; /* Dummy variable */ int i; MPI_Comm_size(comm, &p); MPI_Comm_rank(comm, &id); datum_size = get_size(dtype); if (!id) { print_subvector(v, dtype, BLOCK_SIZE(id,p,n)); if (p>1) { tmp = my_malloc(id, BLOCK_SIZE(p-1,p,n)*datum_size); for (i=1; i<p; ++i) { MPI_Send(&prompt, 1, MPI_INT, i, PROMPT_MSG, comm); MPI_Recv(tmp, BLOCK_SIZE(i,p,n), dtype, i, RESPONSE_MSG, comm, &status); print_subvector(tmp, dtype, BLOCK_SIZE(i,p,n)); } free(tmp); } printf("\n\n"); } else { MPI_Recv(&prompt, 1, MPI_INT, 0, PROMPT_MSG, comm, &status); MPI_Send(v, BLOCK_SIZE(id,p,n), dtype, 0, RESPONSE_MSG, comm); } return;}/* * Process 0 prints a vector that is replicated among * the processes in a communicator. */void print_replicated_vector( void *v, /* IN - Address of vector */ MPI_Datatype dtype, /* IN - Vector element type */ int n, /* IN - Vector length */ MPI_Comm comm) /* IN - Communicator */{ int id; /* Process rank */ MPI_Comm_rank(comm, &id); if (!id) { print_subvector(v, dtype, n); printf("\n\n"); } return;}
1 0
- Michael J. Quinn, 《Parallel Programming in C with MPI and OpenMP》程序代码
- Begin Parallel Programming With OpenMP
- Mixed MPI-OpenMP programming
- Parallel Programming with CUDA
- Concurrent and Parallel Programming
- Using OpenMP: Portable Shared Memory Parallel Programming
- Introduction to Parallel and Concurrent Programming in Python
- Parallel and Concurrent Programming in Haskell.pdf 英文原版 免费下载
- 《Pro .Net 4 Parallel Programming in C#》笔记
- parallel programming in java introduce
- Getting Started with CGI Programming in C
- Re: Programming in C with Bluetooth Sockets
- openMP & MPI
- MPI & OpenMP
- MPI & OpenMP
- Parallel Programming with Microsoft Visual C++
- Programming in C++, Rules and Recommendations
- A C++ Demo Code for parallel Computing with openMP
- 南大软院大神养成计划第十六天
- 【LeetCode】283Move Zeroes
- C-014.循环嵌套--九九乘法表
- C++文件操作
- Eclipse的中文字体很小
- Michael J. Quinn, 《Parallel Programming in C with MPI and OpenMP》程序代码
- Linux之tcp的结构分析
- 虚拟存储器和cache的异同
- 第一次写博客,坚持下去。
- DDlog日志输出
- POJ2377 Bad Cowtractors
- 【JAVA大作业开发记录(七)】
- HDU 1004 (字典树||map)
- 【LeetCode】217Contains Duplicate