使用 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上组装,所以结果不正确。
作为风格问题,您可以考虑去掉全局变量,改为向子例程添加参数。
#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上组装,所以结果不正确。
作为风格问题,您可以考虑去掉全局变量,改为向子例程添加参数。