0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#include <time.h>
#include <math.h>
#include <sys/time.h>

#define NUM 512

int id,nproc;
int colorbuf[NUM * NUM];
double cx0,cx1,cy0,cy1;
int n;
double dx,dy;
int p_n;
struct timeval startTime, endTime;
double timeused_p;


void draw()
{
int i = 0;
int j = 0;
int k = 0;
FILE *fp = fopen("001.ppm", "wb");
fprintf(fp, "P6\n# Mandelbrot, xmin=%d, xmax=%d, ymin=%d, ymax=%d, maxiter=%d\n%d\n%d\n%d\n",-2,2,-2,2,NUM,NUM,NUM,(NUM < 256 ? 256 : NUM));
for (j=0;j<n;j++)
{    
    for(i=0;i<n;i++) 
    {        
        int temp=colorbuf[j*n+i];
    if (temp == NUM)
    {
    const unsigned char black[] = {0,0,0};
    fwrite(black, 3, 1, fp);
    }
    else
    {
    unsigned char color[3];
    color[0] = temp >> 8;
    color[1] = temp & 255;
    color[2] = temp >> 8;
    fwrite(color, 3, 1, fp);
    };
} 

}
fclose(fp);
}

int compColor(double creal, double cimage)
{
double real, image;
double nreal, nimage;
double tmp;
int i;

real = creal;
image = cimage;

for (i = 0; i < NUM; i++) 
{
    tmp = real*real + image*image;
    if (tmp >= 4.0) return i;
    nreal = real*real - image*image + creal;
    nimage = real*image*2.0 + cimage;
    real = nreal;
    image = nimage;
}

return NUM;
}

void colorCalculate()
{
dx=(cx1-cx0)/n;
dy=(cy1-cy0)/n;
int locN=n/nproc;
int i,j,k;
double cx,cy;
for (j=id*locN;j<=id*locN+locN-1;j++)
{  
    cy= cy0+j*dy;    
    for(i=0;i<n;i++) 
    {       
        cx=cx0+i*dx; 
        colorbuf[j*n+i]=compColor(cx, cy);
    }
 }
}


int main()
{ 
MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&id);//id存放进程的标识
MPI_Comm_size(MPI_COMM_WORLD,&nproc);//nproc存放总进程数
if(id==0)
{
    gettimeofday(&startTime, NULL);
    cx0=-2;
    cx1=2;
    cy0=-2;
    cy1=2;
    n=NUM;
}

MPI_Bcast(&cx0, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(&cx1, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(&cy0, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(&cy1, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

colorCalculate();
int locN=n/nproc;

if(id!=0){
     MPI_Gather(&colorbuf, locN*n, MPI_INT, &colorbuf[id*locN*n], locN*n, MPI_INT, 0, MPI_COMM_WORLD);
}

if(id==0){
 gettimeofday(&endTime, NULL);
 timeused_p =  1000000 * (endTime.tv_sec - startTime.tv_sec) + endTime.tv_usec - startTime.tv_usec;
timeused_p /= 1000;
printf("静态调度运行时间 : %f ms\n", timeused_p);
draw();
}

MPI_Barrier(MPI_COMM_WORLD);        
MPI_Finalize();      
return 0; 
}

Here is the C + mpi code to realize the mandelbrot set using statistic mode. And here is the run command. My environment is ubuntu 14.04. enter image description here

And here is the result: enter image description here

It's not normal. It seems that there is only half of the image. I really don't know what's wrong. Sorry for the long and dump code. Anyone could help?

L.Y.C
  • 41
  • 2
  • 8

2 Answers2

0

I think you have typo , look at these lines

    cx0=-2;
    cx1=2;
    cy1=-2;  // <- should be cy0 
    cy1=2;   // 

remember that cy0 is defined as global variable, so its default value is 0.0, so as the result of this you got half of image.

Why are you writing data to file as 6 bytes sequence. According to reference https://en.wikipedia.org/wiki/Netpbm_format

PPM uses 24 bits per pixel: 8 for red, 8 for green, 8 for blue

so you should change these lines

const unsigned char black[] = {0,0,0,0,0,0};
fwrite(black, 6, 1, fp);

to

const unsigned char black[] = {0,0,0};
fwrite(black, 3, 1, fp);

and

unsigned char color[6];
color[0] = temp >> 8;
    color[1] = temp & 255;
    color[2] = temp >> 8;
    color[3] = temp & 255;
    color[4] = temp >> 8;
    color[5] = temp & 255;
fwrite(color, 6, 1, fp);

to

unsigned char color[3];
color[0] = red; 
color[1] = green;
color[2] = blue;
fwrite(color, 3, 1, fp);

values red,green,blue depend on temp value (0-512), so you should scale this value into range 0-255.

rafix07
  • 20,001
  • 3
  • 20
  • 33
  • Ah, yes. Thank you. But after I correct this, the ppm shows nothing. I still have no idea. – L.Y.C Feb 13 '18 at 10:01
  • Hi, I have edited the code, but it still shows half of the picture. – L.Y.C Feb 13 '18 at 11:48
  • @L.Y.C I don't know what is the purpose of `id` in colorCalculate function, but if this value is 0, you fill only `n/nproc` upper rows, what i can see on pasted image. – rafix07 Feb 13 '18 at 12:04
  • `id` means the identity of the processor. – L.Y.C Feb 13 '18 at 12:14
0

all the ranks must invoke MPI_Gather(), and with the parameters in the right order. Since colorbuf is used as both send and receive buffer, MPI_IN_PLACE has to be used.

Since the data is small enough, non root ranks do not hang, but colorbuf is not assembled on the root rank, and hence the incorrect results.

As a matter of style, you might consider getting rid of the global variables, and adding parameters to your subroutines instead.

Gilles Gouaillardet
  • 8,193
  • 11
  • 24
  • 30