/*
* MPI Mandelbrot program using dynamic task assignment
*
* This program computes and displays all or part of the Mandelbrot
* set. By default, it examines all points in the complex plane
* that have both real and imaginary parts between -2 and 2.
* Command-line parameters allow zooming in on a specific part of
* this range.
*
* Usage:
* mandelbrot maxiter [x0 y0 size]
* where
* maxiter denotes the maximum number of iterations at each point
* x0, y0, and size specify the range to examine (a square
* centered at x0 + iy0 of size 2*size by 2*size -- by default,
* a square of size 4 by 4 centered at the origin)
*
* Input: none, except the optional command-line arguments
* Output: a graphical display as described in Wilkinson & Allen,
* displayed using the X Window system, plus text output to
* standard output showing the above parameters, plus execution
* time in seconds.
*
*
* Code originally obtained from Web site for Wilkinson and Allen's
* text on parallel programming:
* http://www.cs.uncc.edu/~abw/parallel/par_prog/
*
* Reformatted and revised by B. Massingill.
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <mpi.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
/* Default values for things. */
#define N 2 /* size of problem space (x, y from -N to N) */
#define NPIXELS 800 /* size of display window in pixels */
/* Constants for message-passing */
#define WORK_TAG 1 /* "work" message (master to worker) */
#define DATA_TAG 2 /* "data" message (worker to master) */
#define STOP_TAG 3 /* "stop" message (master to worker) */
/* Structure definition for complex numbers */
typedef struct {
double real, imag;
} complex;
/* Functions for GUI */
#include "mandelbrot-gui.h" /* has setup(), interact() */
/* ---- Function declarations ---- */
int master_pgm(int nworkers, int width, int height,
double real_min, double real_max,
double imag_min, double imag_max,
int maxiter);
int worker_pgm(int myID, int width, int height,
double real_min, double real_max,
double imag_min, double imag_max,
int maxiter);
/* ---- Main program ---- */
int main (int argc, char *argv[]) {
int nprocs;
int myid;
int returnval;
int maxiter;
double real_min = -N;
double real_max = N;
double imag_min = -N;
double imag_max = N;
int width = NPIXELS; /* dimensions of display window */
int height = NPIXELS;
/* Initialize for MPI */
if (MPI_Init(&argc, &argv) != MPI_SUCCESS) {
fprintf(stderr, "MPI initialization error\n");
exit(EXIT_FAILURE);
}
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
if (nprocs < 2) {
fprintf(stderr, "Number of processes must be at least 2\n");
MPI_Finalize(); exit(EXIT_FAILURE);
}
/* Check command-line arguments */
if ((argc < 2) || ((argc > 2) && (argc < 5))) {
if (myid == 0) {
fprintf(stderr, "usage: %s maxiter [x0 y0 size]\n", argv[0]);
}
MPI_Finalize(); exit(EXIT_FAILURE);
}
/* Process command-line arguments */
maxiter = atoi(argv[1]);
if (argc > 2) {
double x0 = atof(argv[2]);
double y0 = atof(argv[3]);
double size = atof(argv[4]);
real_min = x0 - size;
real_max = x0 + size;
imag_min = y0 - size;
imag_max = y0 + size;
}
/* Call master or worker code as appropriate */
if (myid == 0) {
returnval = master_pgm(nprocs-1, width, height,
real_min, real_max, imag_min, imag_max, maxiter);
}
else {
returnval = worker_pgm(myid, width, height,
real_min, real_max, imag_min, imag_max, maxiter);
}
/* Finish up */
MPI_Finalize();
return returnval;
}
/*
* ---- Program for master process ----
*
* Contains most code from original main program, slightly modified for MPI.
* Returns EXIT_SUCCESS or EXIT_FAILURE as appropriate.
*/
int master_pgm(int nworkers, int width, int height,
double real_min, double real_max,
double imag_min, double imag_max,
int maxiter) {
Display *display;
Window win;
GC gc;
long min_color, max_color;
int this_row, next_row;
int p;
double start_time, end_time;
long *data_msg = malloc((width+1) * sizeof(long));
MPI_Status status;
int col;
int tasks_not_done;
int id;
int setup_return;
/* Initialize for graphical display */
setup_return =
setup(width, height, &display, &win, &gc, &min_color, &max_color);
if (setup_return != EXIT_SUCCESS) {
fprintf(stderr, "Unable to initialize display, continuing\n");
}
/* (if not successful, continue but don't display results) */
/* Start timing */
start_time = MPI_Wtime();
/* START OF CHANGED SECTION */
/* Broadcast values workers will need and can't compute */
MPI_Bcast(&min_color, 1, MPI_LONG, 0, MPI_COMM_WORLD);
MPI_Bcast(&max_color, 1, MPI_LONG, 0, MPI_COMM_WORLD);
/* Set up for dynamic task assignment */
next_row = 0; /* next row to assign to a worker */
tasks_not_done = 0; /* count of workers still working */
/* Send each worker first row to work on */
for (p = 0; p < nworkers; ++p) {
MPI_Send(&next_row, 1, MPI_INT, p+1, WORK_TAG, MPI_COMM_WORLD);
++next_row;
++tasks_not_done;
}
/* Receive results from workers and draw points */
while (tasks_not_done > 0) {
/* Receive a row from a worker */
MPI_Recv(data_msg, width+1, MPI_LONG, MPI_ANY_SOURCE,
DATA_TAG, MPI_COMM_WORLD, &status);
--tasks_not_done;
id = status.MPI_SOURCE;
/* More rows? */
if (next_row < height) {
/* If so, give this worker another row to work on */
MPI_Send(&next_row, 1, MPI_INT, id, WORK_TAG, MPI_COMM_WORLD);
++next_row;
++tasks_not_done;
}
else {
/* Otherwise shut this worker down */
MPI_Send(&next_row, 0, MPI_INT, id, STOP_TAG, MPI_COMM_WORLD);
}
/* Display received data */
this_row = data_msg[0];
for (col = 0; col < width; ++col) {
if (setup_return == EXIT_SUCCESS) {
XSetForeground (display, gc, data_msg[col+1]);
XDrawPoint (display, win, gc, col, this_row);
}
}
}
/* END OF CHANGED SECTION */
/* Be sure everything is written out. */
if (setup_return == EXIT_SUCCESS) {
XFlush (display);
}
/* End timing */
end_time = MPI_Wtime();
/* Produce text output */
fprintf(stdout, "\n");
fprintf(stdout, "MPI program with dynamic task assignment\n");
fprintf(stdout, "number of worker processes = %d\n", nworkers);
fprintf(stdout, "center = (%g, %g), size = %g\n",
(real_max + real_min)/2, (imag_max + imag_min)/2,
(real_max - real_min)/2);
fprintf(stdout, "maximum iterations = %d\n", maxiter);
fprintf(stdout, "execution time in seconds = %g\n", end_time - start_time);
fprintf(stdout, "\n");
/* Wait for user response, then exit program */
if (setup_return == EXIT_SUCCESS) {
interact(display, &win, width, height,
real_min, real_max, imag_min, imag_max);
}
free(data_msg);
return EXIT_SUCCESS;
}
/*
* ---- Program for worker process ----
*
* Returns EXIT_SUCCESS or EXIT_FAILURE as appropriate.
*/
int worker_pgm(int myID, int width, int height,
double real_min, double real_max,
double imag_min, double imag_max,
int maxiter) {
MPI_Status status;
int the_row;
long min_color, max_color, color;
double scale_real, scale_imag, scale_color;
long *data_msg =
mandelbrot-mpi-dynamic.rar_MPI_MPI dynamic_Mandelbrot_mandelbrot
版权申诉
162 浏览量
2022-09-23
11:08:32
上传
评论
收藏 3KB RAR 举报
Kinonoyomeo
- 粉丝: 76
- 资源: 1万+
最新资源
- Picasso_v3.1 2.ipa
- chromedriver-mac-arm64.zip
- 蓝zapro.apk
- chromedriver-linux64.zip
- UCAS研一深度学习实验-MNIST手写数字识别python源码+详细注释(高分项目)
- 基于Python和PyTorch框架完成的一个手写数字识别实验源码(带MINIST手写数字数据集)+详细注释(高分项目)
- 基于Matlab在MNIST数据集上利用CNN完成手写体数字识别任务,并实现单层CNN反向传播算法+源代码+文档说明(高分项目)
- NVIDIA驱动、CUDA和Pytorch及其依赖
- 基于SVM多特征融合的微表情识别python源码+项目说明+详细注释(高分课程设计)
- html动态爱心代码一(附源码)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈