使用c + mpi

时间:2018-02-13 09:23:17

标签: mpi mandelbrot

#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代码。这是run命令。我的环境是ubuntu 14.04。 enter image description here

结果如下: enter image description here

这不正常。似乎只有一半的图像。我真的不知道出了什么问题。 抱歉,我们有很长的转储代码。 有人可以帮忙吗?

2 个答案:

答案 0 :(得分:0)

我认为你有拼写错误,看看这些行

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

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

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

  

PPM每像素使用24位:红色为8位,绿色为8位,蓝色为8位

所以你应该改变这些行

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范围内。

答案 1 :(得分:0)

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

由于数据足够小,非根等级不会挂起,但colorbuf未在根等级上汇编,因此结果不正确。

作为一种风格问题,您可以考虑删除全局变量,并将参数添加到子例程中。