使用 c + mpi 在 statistic mandelbrot 中显示 bmp

display bmp in statistic mandelbrot using c + mpi

#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; 
}

这里是使用统计模式实现mandelbrot集的C+mpi代码。这是 运行 命令。我的环境是ubuntu14.04。

结果如下:

这不正常。好像只有一半的图像。我真的不知道怎么了。 抱歉,长代码和转储代码。 有人可以帮忙吗?

我认为你打错了,看看这些行

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

记住cy0被定义为全局变量,所以它的默认值是0.0,所以你得到了一半的图像。

为什么要将数据作为 6 字节序列写入文件。根据参考 https://en.wikipedia.org/wiki/Netpbm_format

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

所以你应该更改这些行

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

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

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);

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

值红色、绿色、蓝色取决于 temp 值 (0-512),因此您应该将此值缩放到 0-255 范围内。

all 行列必须调用 MPI_Gather(),并且参数顺序正确。由于 colorbuf 用作发送和接收缓冲区,因此必须使用 MPI_IN_PLACE

由于数据足够小,non root ranks不挂,但是colorbuf没有在root rank上组装,所以结果不正确。

作为风格问题,您可以考虑去掉全局变量,改为向子例程添加参数。