混合openmp mpi mandelbrot代码

混合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的mpi版本,效果非常好。然后我必须使用openmp实现一个混合版本。我将openmp并行化与所有计算(内部函数calculoMandelbrot)一起放在循环中。如果我删除omp指令(omp用于并行和omp屏障),它工作得非常好(这是我的mpi实现)。我应该工作,但我猜不出我在哪里迷路了

Im有一个IMAGEHEIGHT*IMAGEWIDTH的图像,每个进程都将其作为一部分(例如:如果我有一个100高度的图像,有4个进程,每个进程计算25行,在calculoMandelbrot函数中完成)。然后我向master发送一条消息,其中包含每个进程中其部分的计算结果

结果是ppm一团糟。不知道为什么。。。任何帮助都将被感激

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