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

📄 master.c

📁 并行计算的例子程序 环境需要lam/Linux 可从lam-mpi.org找到
💻 C
字号:
/* * Copyright (c) 2001-2002 The Trustees of Indiana University.   *                         All rights reserved. * Copyright (c) 1998-2001 University of Notre Dame.  *                         All rights reserved. * Copyright (c) 1994-1998 The Ohio State University.   *                         All rights reserved. *  * This file is part of the LAM/MPI software package.  For license * information, see the LICENSE file in the top level directory of the * LAM/MPI source distribution. *  * $HEADER$ * * $Id: master.c,v 6.12 2003/04/23 22:32:12 jsquyres Exp $ * *	Function:	- master program of mandelbrot demo *			- fault tolerant version *			- distributes work orders to the slaves *			- collects pixel buffers from the slaves *			- creates a Sun rasterfile from the total result *			- grid means the whole domain *			- region means the subdomain * *	Returns:	- errno if fatal error terminated program */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <mpi.h>#include "mandel.h"#define min(a,b)	(((a) < (b)) ? (a) : (b))/* * local structures */struct sunras{				/* Sun raster file header */  int ras_magic;  int ras_width;  int ras_height;  int ras_depth;  int ras_length;  int ras_type;  int ras_maptype;  int ras_maplength;};struct work{				/* work order */  int wrk_x_lb;  int wrk_x_ub;  int wrk_y_lb;  int wrk_y_ub;  struct work *wrk_next;};/* * local functions */static int harvest(void);	/* gets results */static void seed(int isslave);	/* distributes work */static void color_map(int fd);	/* generate color map */static void insert(struct work *work);	/* insert work into list *//* * local variables */static int grid_dimx;		/* grid size in pixels */static int grid_dimy;		/* grid size in pixels */static int region_dimx;		/* region size in pixels */static int region_dimy;		/* region size in pixels */static char *grid;		/* color buffer buffer */static int ntasks;		/* # compute tasks */static int nwork_out;		/* # work items out there */static struct work *work_bottom;	/* bottom of work list */static struct work *work_top;	/* top of work list */static struct work **work_slaves;	/* slave's current work */static MPI_Request *req_slaves;	/* receive reqs from slaves */static MPI_Comm *icomm_slaves;	/* inter comm. to each slave */static MPI_Datatype dtype_region;	/* place region into grid */intmain(int argc, char *argv[]){  float grid_coord[4];		/* complex grid description */  float init[4];		/* scale and translate data */  int islave;			/* harvested slave index */  int n, i;  int x, y;			/* pixel coordinates */  int fd;			/* output raster file */  struct work *p;  struct sunras rasterfile;  int return_status = 0;	/* Return status for master */  int err;  MPI_Info appInfo;  int flag;  char filename[128];  FILE *fp;  void **attrp;  /* Initialize MPI. */  MPI_Init(&argc, &argv);  MPI_Comm_size(MPI_COMM_WORLD, &ntasks);  /* Check that we are the only master */  if (ntasks != 1) {    printf("Too many masters. Please launch only 1 copy of\n");    printf("the master program. It will use MPI_Comm_spawn()\n");    printf("to create the slaves.\n");    MPI_Abort(MPI_COMM_WORLD, (1 << 16) + 1);  }  /* Get universe size */  MPI_Attr_get(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, &attrp, &flag);  if (flag == 1) {    ntasks = (int) *attrp;  } else {    printf("This MPI does not support Universe Size, which is needed\n");    printf("for this example. \n");    MPI_Abort(MPI_COMM_WORLD, (1 << 16) + 1);  }  /* Allocate slave communicator arrays. */  icomm_slaves = (MPI_Comm *)    malloc((unsigned) (ntasks * sizeof(MPI_Comm)));  if (icomm_slaves == NULL)    MPI_Abort(MPI_COMM_WORLD, (errno << 16) + 1);  /* Spawn off the slaves */  sprintf(filename, "./lam_fault_appschema.%d", (int) getpid());  MPI_Info_create(&appInfo);  MPI_Info_set(appInfo, "file", filename);  for (i = 0; i < ntasks; ++i) {    /* Create a temporary app schema file */    fp = fopen(filename, "w");    if (fp == NULL) {      printf("Could not open file %s\n", filename);      MPI_Finalize();      return 1;    }    fprintf(fp, "c%d ./slave\n", i);    fclose(fp);    /* Spawn */    MPI_Comm_spawn(0, MPI_ARGV_NULL, 0,		   appInfo, 0, MPI_COMM_SELF, &(icomm_slaves[i]),		   &err);    if (err != MPI_SUCCESS) {      printf("Spawn Error %d\n", err);      MPI_Abort(MPI_COMM_WORLD, (err << 16) + 1);    }   }  MPI_Info_free(&appInfo);  unlink(filename);  /* Hardcode the universe. */  grid_coord[0] = -2;  grid_coord[1] = 1.25;  grid_coord[2] = 0.5;  grid_coord[3] = -1.25;  grid_dimx = 512;  grid_dimy = 512;  region_dimx = 16;  region_dimy = 16;  /* Allocate the raster file buffer. */  grid = malloc((unsigned) (grid_dimx * grid_dimy));  if (grid == NULL)    MPI_Abort(MPI_COMM_WORLD, errno);  /* Allocate slave receive request array. */  req_slaves = (MPI_Request *)    malloc((unsigned) (ntasks * sizeof(MPI_Request)));  if (req_slaves == NULL)    MPI_Abort(MPI_COMM_WORLD, (errno << 16) + 1);  for (n = 0; n < ntasks; ++n)    req_slaves[n] = MPI_REQUEST_NULL;  /* Allocate slave work ptr array. */  work_slaves = (struct work **)    malloc((unsigned) (ntasks * sizeof(struct work *)));  if (work_slaves == NULL)    MPI_Abort(MPI_COMM_WORLD, (errno << 16) + 1);  /* Create a datatype to receive a region into the grid.  To   * handle partial regions at the edges of the grid, we need   * three extra datatypes.  Right now we are lazy and the   * region must evenly divide the grid.  */  MPI_Type_vector(region_dimy, region_dimx, grid_dimx, MPI_CHAR,		  &dtype_region);  MPI_Type_commit(&dtype_region);  /* Send translate and scale factors to each slave. */  init[0] = (grid_coord[2] - grid_coord[0]) / grid_dimx;  init[1] = -((grid_coord[1] - grid_coord[3]) / grid_dimy);  init[2] = grid_coord[0];  init[3] = grid_coord[1];  for (n = 0; n < ntasks; ++n)    MPI_Send((void *) init, 4, MPI_FLOAT, 0, WORKTAG, icomm_slaves[n]);  /* set communicators error handlers */  for (n = 0; n < ntasks; ++n)    MPI_Errhandler_set(icomm_slaves[n], MPI_ERRORS_RETURN);  MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);  /* Create the work list. */  for (y = 0; y < grid_dimy; y += region_dimy) {    for (x = 0; x < grid_dimx; x += region_dimx) {      p = (struct work *)	malloc((unsigned) sizeof(struct work));      if (p == 0)	MPI_Abort(MPI_COMM_WORLD, errno);      p->wrk_x_lb = x;      p->wrk_x_ub = min(x + region_dimx, grid_dimx) - 1;      p->wrk_y_lb = y;      p->wrk_y_ub = min(y + region_dimy, grid_dimy) - 1;      p->wrk_next = 0;      insert(p);    }  }  nwork_out = 0;  /* Distribute work to slaves until all the answers have been   * received or their are no more living slaves. */  while (work_top) {    /* Distribute a work order to all living slaves. */    for (n = 0; work_top && (n < ntasks); ++n) {      if (icomm_slaves[n] == MPI_COMM_NULL)	continue;      seed(n);    }    if (nwork_out == 0) {      printf("master: all slaves are dead\n");      MPI_Abort(MPI_COMM_WORLD, 1);    }    /* Collect results and issue new work orders until there are     * no outstanding work orders. */    do {      islave = harvest();      if (islave < 0)		       /* a node has died */	++return_status;      if ((islave >= 0) && work_top)	seed(islave);    } while (nwork_out > 0);    /* After letting living slaves idle due to lack of work, new     * work orders may appear from slaves that die later.  So     * start this whole process over with the remaining work     * orders and living slaves. */  }  /* We have all the answers now, so kill the living workers. */  for (n = 0; n < ntasks; ++n) {    if (icomm_slaves[n] == MPI_COMM_NULL)      continue;    err = MPI_Send((void *) 0, 0, MPI_INT, 0, DIETAG, icomm_slaves[n]);    if (err != MPI_SUCCESS)      MPI_Comm_free(&icomm_slaves[n]);  }  /* Store grid as a Sun rasterfile. Try viewing it with xv. */  rasterfile.ras_magic = 0x59a66a95;  rasterfile.ras_width = grid_dimx;  rasterfile.ras_height = grid_dimy;  rasterfile.ras_depth = 8;  rasterfile.ras_length = grid_dimx * grid_dimy;  rasterfile.ras_type = 1;  rasterfile.ras_maptype = 1;  rasterfile.ras_maplength = 768;  fd = open("mandel.out", O_CREAT | O_TRUNC | O_WRONLY, 0644);  if (fd < 0) {    printf("master: Not able to write to file mandle.out -- aborting\n");    MPI_Abort(MPI_COMM_WORLD, errno);  }  write(fd, (char *) &rasterfile, sizeof(rasterfile));  color_map(fd);  write(fd, grid, grid_dimx * grid_dimy);  close(fd);  /* If any one of the slaves died, abort on just myself   * (MPI_COMM_SELF).  If we abort on MPI_COMM_WORLD, LAM will   * try to kill all processes (one or more of which is now   * already dead and possibly unresponsive, so LAM would hang.   * Hence, just abort on MPI_COMM_SELF).  See the MPI_Abort(3)   * man page for an explanation of the error code. */  if (return_status != 0)    MPI_Abort(MPI_COMM_SELF, (return_status << 16) + 1);  MPI_Finalize();  return (0);}/* *	harvest * *	Function:	- receives results from one slave *      Returns:        - slave's index or -1 */static intharvest(void){  int err;  int idone;  nwork_out--;  err = MPI_Waitany(ntasks, req_slaves, &idone, MPI_STATUS_IGNORE);  if (err != MPI_SUCCESS) {    if (idone >= 0) {      req_slaves[idone] = MPI_REQUEST_NULL;      MPI_Comm_free(&icomm_slaves[idone]);      insert(work_slaves[idone]);    }    return (-1);  }  return (idone);}/* *	seed * *	Function:	- sends out work request */static voidseed(int islave){  char *pgrid;			/* ptr within grid buffer */  int err;  printf("master: allocating block (%d, %d) - (%d, %d) to process %d\n",	 work_top->wrk_x_lb, work_top->wrk_y_lb,	 work_top->wrk_x_ub, work_top->wrk_y_ub, islave);  err = MPI_Send((void *) work_top, 4, MPI_INT, 0, WORKTAG,		 icomm_slaves[islave]);  if (err != MPI_SUCCESS) {    MPI_Comm_free(&icomm_slaves[islave]);    return;  }  ++nwork_out;  pgrid = grid + (grid_dimx * work_top->wrk_y_lb + work_top->wrk_x_lb);  work_slaves[islave] = work_top;  work_top = work_top->wrk_next;  err = MPI_Irecv(pgrid, 1, dtype_region, 0, REPLYTAG, icomm_slaves[islave],		  &req_slaves[islave]);  if (err != MPI_SUCCESS) {    req_slaves[islave] = MPI_REQUEST_NULL;    MPI_Comm_free(&icomm_slaves[islave]);    insert(work_slaves[islave]);    --nwork_out;  }}/* *	color_map * *	Function:	- generate and write a color map to a file *			- I don't know anything about graphics. *	Accepts:	- file descriptor */static voidcolor_map(int fd){  int i;			/* color map index */  int r, g, b;			/* individual color map indices */  unsigned char red[256];	/* trivial color map */  unsigned char green[256];	/* trivial color map */  unsigned char blue[256];	/* trivial color map */  i = 0;  for (b = 0; b < 3; ++b) {    for (g = 0; g < 7; ++g) {      for (r = 0; r < 7; ++r) {	red[i] = (r << 5) | 0x10;	green[i] = (g << 5) | 0x10;	blue[i] = (b << 6) | 0x20;	++i;      }    }  }  write(fd, (char *) red, sizeof(red));  write(fd, (char *) green, sizeof(green));  write(fd, (char *) blue, sizeof(blue));}/* *	insert * *	Function:	- inserts work order into a list */static voidinsert(struct work *pwrk){  if (work_top == 0) {    work_top = pwrk;  }  if (work_bottom != 0) {    work_bottom->wrk_next = pwrk;  }  work_bottom = pwrk;  pwrk->wrk_next = 0;}

⌨️ 快捷键说明

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