混合openmp mpi mandelbrot代码
我面临一个问题:我做了mandelbrot的mpi版本,效果非常好。然后我必须使用openmp实现一个混合版本。我将openmp并行化与所有计算(内部函数calculoMandelbrot)一起放在循环中。如果我删除omp指令(omp用于并行和omp屏障),它工作得非常好(这是我的mpi实现)。我应该工作,但我猜不出我在哪里迷路了 Im有一个IMAGEHEIGHT*IMAGEWIDTH的图像,每个进程都将其作为一部分(例如:如果我有一个100高度的图像,有4个进程,每个进程计算25行,在calculoMandelbrot函数中完成)。然后我向master发送一条消息,其中包含每个进程中其部分的计算结果 结果是ppm一团糟。不知道为什么。。。任何帮助都将被感激混合openmp mpi mandelbrot代码,mpi,openmp,hybrid,mandelbrot,Mpi,Openmp,Hybrid,Mandelbrot,我面临一个问题:我做了mandelbrot的mpi版本,效果非常好。然后我必须使用openmp实现一个混合版本。我将openmp并行化与所有计算(内部函数calculoMandelbrot)一起放在循环中。如果我删除omp指令(omp用于并行和omp屏障),它工作得非常好(这是我的mpi实现)。我应该工作,但我猜不出我在哪里迷路了 Im有一个IMAGEHEIGHT*IMAGEWIDTH的图像,每个进程都将其作为一部分(例如:如果我有一个100高度的图像,有4个进程,每个进程计算25行,在calc
/
// mandelbrot.c
//
//
// The Mandelbrot calculation is to iterate the equation
// z = z*z + c, where z and c are complex numbers, z is initially
// zero, and c is the coordinate of the point being tested. If
// the magnitude of z remains less than 2 for ever, then the point
// c is in the Mandelbrot set. In this code We write out the number of iterations
// before the magnitude of z exceeds 2, or UCHAR_MAX, whichever is
// smaller.//
//
//
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <omp.h>
#include <math.h>
#define TAG_ENVIO 3
int IMAGEWIDTH = 600;
int IMAGEHEIGHT = 400;
int ITERATIONS = 100000;
int CHUNK = 1;
int SIZE;
void escribirfichero(char* pixels) {
int i;
FILE *fp;
fp = fopen("MandelbrotSet.ppm", "w");
if (fp == NULL) {
perror ( "Unable to open file" );
exit (EXIT_FAILURE);
}
//printf("Empezamos a escribir en el fichero");
fprintf(fp, "P6\n# CREATOR: mandel program\n");
fprintf(fp, "%d %d\n255\n", IMAGEWIDTH, IMAGEHEIGHT);
for (i = 0; i < (IMAGEWIDTH*3*IMAGEHEIGHT); i++)
fputc((char) pixels[i],fp);
fclose(fp);
}
void calculoMandelbrot(char *destino, int iproc, int height)
{
int posInici = iproc * height;
int xactual, yactual;
int posLocal = 0;
int chunkSize = height * IMAGEWIDTH * 3;
omp_set_dynamic(1);
//each iteration, it calculates: newz = oldz*oldz + p, where p is the current pixel, and oldz stars at the origin
double pr, pi; //real and imaginary part of the pixel p
double newRe, newIm, oldRe, oldIm; //real and imaginary parts of new and old z
double zoom = 1, moveX = -0.5, moveY = 0; //you can change these to zoom and change position
int numcpu = omp_get_num_procs();
omp_set_num_threads(numcpu);
if(iproc != 0)
destino = (char *)malloc(sizeof(char) * chunkSize);
#pragma omp parallel //shared(moveX, moveY, zoom) private(xactual, yactual, pr, pi, newRe, newIm) if (numcpu>1)
{
#pragma omp for schedule(dynamic) //, CHUNK
for(yactual = posInici; yactual < posInici + height; yactual++)
{
for(xactual = 0; xactual < IMAGEWIDTH; xactual++)
{
//calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
pr = 1.5 * (xactual - IMAGEWIDTH / 2) / (0.5 * zoom * IMAGEWIDTH) + moveX;
pi = (yactual - IMAGEHEIGHT / 2) / (0.5 * zoom * IMAGEHEIGHT) + moveY;
newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0
//"i" will represent the number of iterations
int i;
//start the iteration process
for(i = 0; i < ITERATIONS; i++)
{
//remember value of previous iteration
oldRe = newRe;
oldIm = newIm;
//the actual iteration, the real and imaginary part are calculated
newRe = oldRe * oldRe - oldIm * oldIm + pr;
newIm = 2 * oldRe * oldIm + pi;
//if the point is outside the circle with radius 2: stop
if((newRe * newRe + newIm * newIm) > 4) break;
}
if(i == ITERATIONS)
{
//escribirArray(destino, posLocal, 0, 0, 0);
destino[posLocal] = 0;
destino[++posLocal] = 0;
destino[++posLocal] = 0;
++posLocal; //me preparo para colocar siguiente.
}
else
{
double z = sqrt(newRe * newRe + newIm * newIm);
int brightness = 256 * log2(1.75 + i - log2(log2(z))) / log2((double)ITERATIONS);
//escribirArray(envioArr, xactual, yactual, brightness, brightness, 255);
destino[posLocal] = brightness;
destino[++posLocal] = brightness;
destino[++posLocal] = 255;
++posLocal; //me preparo para colocar siguiente
}
}
}
}
#pragma omp barrier
if(iproc != 0)
{
MPI_Send(destino, chunkSize, MPI_CHAR, 0, TAG_ENVIO, MPI_COMM_WORLD);
free(destino);
}
}
void stringCopy(char *pixels, char *reciboArr, int sender, int height)
{
int posInici = sender * height * IMAGEWIDTH*3;
int pos;
for (pos = 0; pos < height * IMAGEWIDTH*3; pos++, posInici++) {
pixels[posInici] = reciboArr[pos];
}
}
int main(int argc, char** argv) {
// mandelbrot
char* pixels;
// mpi
int nproc, iproc;
// calculos tiempo
double begin;
double end_calc;
double end_total;
if(argc >= 3)
{
// se supone que la línia de ejecucion sera del tipo
// -n 4 ${workspace_loc:MPI}/Debug/MPI${build_files} 100 200
// FALTA PROVAR EN MOORE
IMAGEWIDTH = atoi(argv[1]);
IMAGEHEIGHT = atoi(argv[2]);
}
if(argc == 4)
{
ITERATIONS = atoi(argv[3]);
}
if(argc == 5)
{
CHUNK = atoi(argv[4]);
}
SIZE = IMAGEHEIGHT * IMAGEWIDTH * 3;
if (MPI_Init(&argc, &argv) != MPI_SUCCESS) {
fprintf(stderr, "Error al inicializar MPI.\n");
return 100;
}
begin = MPI_Wtime();
if (MPI_Comm_size(MPI_COMM_WORLD, &nproc) != MPI_SUCCESS) {
fprintf(stderr, "No se puede obtener el contador de procesos.\n");
MPI_Finalize();
return 101;
} else if (nproc < 2) {
fprintf(stderr, "Se necesitan almenos 2 procesos (se usan %d)\n", nproc);
MPI_Finalize();
return 102;
}
if (MPI_Comm_rank(MPI_COMM_WORLD, &iproc) != MPI_SUCCESS) {
fprintf(stderr, "No se puede obtener el rango para el proceso.\n");
MPI_Finalize();
return 103;
}
if ((IMAGEHEIGHT % nproc) != 0)
{
printf("Incompatable number of processes requested\nExiting...\n");
exit(EXIT_FAILURE);
}
int height = IMAGEHEIGHT/nproc;
int chunkSize = height * IMAGEWIDTH * 3;
if (iproc != 0) {
char *envioArr = (char *)malloc(sizeof(char) * chunkSize);
calculoMandelbrot(envioArr, iproc, height);
}
else if(iproc == 0) {
printf("Empezando los calculos de Mandelbrot...\n");
printf("IMAGEWIDTH %d IMAGEHEIGHT %d ITERATIONS %d num procesos %d CHUNK %d\n", IMAGEWIDTH, IMAGEHEIGHT, ITERATIONS, nproc, CHUNK);
pixels = (char *)malloc(SIZE * sizeof(char));
calculoMandelbrot(pixels, iproc, height);
//inicio recibir el resto de mensajes
char *reciboArr = (char *)malloc(sizeof(char)*chunkSize);
int i;
MPI_Status status;
for (i = 1; i<nproc; i++)
{
MPI_Recv(reciboArr, height*IMAGEWIDTH*3, MPI_CHAR, MPI_ANY_SOURCE, TAG_ENVIO, MPI_COMM_WORLD, &status);
stringCopy(pixels, reciboArr, status.MPI_SOURCE, height);
}
free(reciboArr);
//final de recibir resto de mensajes
end_calc = MPI_Wtime() - begin;
printf("Tiempo en calculos: %.10lf segundos \n", end_calc);
//MPI_Barrier(MPI_COMM_WORLD);
//printf("Escribiendo la imagen\n");
escribirfichero(pixels);
end_total = MPI_Wtime() - begin;
printf("Tiempo en total: %.10lf segundos \n", end_total);
free(pixels);
}
MPI_Finalize();
return 0;
}
/
//曼德布罗特
//
//
//Mandelbrot计算是迭代方程
//z=z*z+c,其中z和c是复数,z最初是
//零,c是被测点的坐标。如果
//z的大小永远小于2,然后是点
//c在Mandelbrot集合中。在这段代码中,我们写出了迭代次数
//在z的大小超过2或UCHAR_MAX之前,以
//小一点//
//
//
#包括
#包括
#包括
#包括
#包括
#定义标签3
int IMAGEWIDTH=600;
int-IMAGEHEIGHT=400;
int迭代次数=100000次;
int CHUNK=1;
整数大小;
无效描述字符集(字符*像素){
int i;
文件*fp;
fp=fopen(“MandelbrotSet.ppm”,“w”);
如果(fp==NULL){
perror(“无法打开文件”);
退出(退出失败);
}
//printf(“Empezamos a describir en el-fichero”);
fprintf(fp,“P6\n#创建者:曼德尔计划”);
fprintf(fp,“%d%d\n255\n”,图像宽度,图像高度);
对于(i=0;i<(图像宽度*3*图像高度);i++)
fputc((字符)像素[i],fp);
fclose(fp);
}
void calculoMandelbrot(字符*destino,内部iproc,内部高度)
{
int posInici=iproc*高度;
事实上,事实上;
int posLocal=0;
int chunkSize=高度*图像宽度*3;
omp_集_动态(1);
//每次迭代,它都会计算:newz=oldz*oldz+p,其中p是当前像素,oldz在原点开始
double pr,pi;//像素p的实部和虚部
double newRe,newIm,oldRe,oldIm;//新z和旧z的实部和虚部
双缩放=1,moveX=-0.5,moveY=0;//您可以将它们更改为缩放和更改位置
int numpu=omp_get_num_procs();
omp_设置_num_线程(numcpu);
如果(iproc!=0)
destino=(char*)malloc(sizeof(char)*chunkSize);
#pragma omp parallel//shared(moveX、moveY、zoom)private(xactual、yactual、pr、pi、newRe、newIm)if(numpu>1)
{
#计划(动态)/,区块的pragma omp
对于(yactual=posInici;yactual4)中断;
}
if(i==迭代次数)
{
//描述(destino,posLocal,0,0,0);
destino[posLocal]=0;
destino[++posLocal]=0;
destino[++posLocal]=0;
++posLocal;//我准备好了。
}
其他的
{
双z=sqrt(newRe*newRe+newIm*newIm);
int亮度=256*log2(1.75+i-log2(log2(z))/log2((双)次迭代);
//描述(Enviroar,xactual,yactual,brightness,brightness,255);
destino[posLocal]=亮度;
destino[++posLocal]=亮度;
destino[++posLocal]=255;
++posLocal;//me preparo para colocar siguiente
}
}
}
}
#布拉格奥姆普屏障
如果(iproc!=0)
{
MPI_发送(destino、chunkSize、MPI_CHAR、0、TAG_ENVIO、MPI_COMM_WORLD);
免费(destino);
}
}
void stringCopy(字符*像素,字符*累加器,整数发送器,整数高度)
{
int posInici=发送器*高度*图像宽度*3;
int pos;
用于(pos=0;pos=3)
{
//这是一个很好的例子
//-n4${workspace\u loc:MPI}/Debug/MPI${build\u files}100 200
//法尔塔·普罗瓦尔·恩摩尔酒店
IMAGEWIDTH=atoi(argv[1]);
IMAGEHEIGHT=atoi(argv[2]);
}
如果(argc==4)
{
迭代次数=atoi(argv[3]);
}
#pragma omp parallel shared ( destino) private ( xactual, yactual)
{
#pragma omp parallel for schedule(static)
for(yactual = posInici; yactual < posInici + height; yactual++)
{
for(xactual = 0; xactual < IMAGEWIDTH; xactual++)
{
//calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
pr = 1.5 * (xactual - IMAGEWIDTH / 2) / (0.5 * zoom * IMAGEWIDTH) + moveX;
pi = (yactual - IMAGEHEIGHT / 2) / (0.5 * zoom * IMAGEHEIGHT) + moveY;
newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0
//"i" will represent the number of iterations
int i;
//start the iteration process
for(i = 0; i < ITERATIONS; i++)
{
//remember value of previous iteration
oldRe = newRe;
oldIm = newIm;
//the actual iteration, the real and imaginary part are calculated
newRe = oldRe * oldRe - oldIm * oldIm + pr;
newIm = 2 * oldRe * oldIm + pi;
//if the point is outside the circle with radius 2: stop
if((newRe * newRe + newIm * newIm) > 4) break;
}
//printf("Antes zona paralela: %d process Thread: %d \n", iproc, numcpu);
if(i == ITERATIONS)
{
//escribirArray(destino, posLocal, 0, 0, 0);
destino[posLocal] = 0;
destino[++posLocal] = 0;
destino[++posLocal] = 0;
++posLocal; //me preparo para colocar siguiente.
}
else
{
double z = sqrt(newRe * newRe + newIm * newIm);
int brightness = 256 * log2(1.75 + i - log2(log2(z))) / log2((double)ITERATIONS);
//escribirArray(envioArr, xactual, yactual, brightness, brightness, 255);
destino[posLocal] = brightness;
destino[++posLocal] = brightness;
destino[++posLocal] = 255;
++posLocal; //me preparo para colocar siguiente
}
}
}
}
#pragma omp barrier
printf("Despuess zona paralela: %d process Thread: %d y posLocal %d \n", iproc, numcpu, posLocal);
if(iproc != 0)
{
MPI_Send(destino, chunkSize, MPI_CHAR, 0, TAG_ENVIO, MPI_COMM_WORLD);
printf("Estoy enviando en el proceso: %d y la posLocal es %d \n", iproc, posLocal);
free(destino);
}