Mandelbrot Apfelmännchen parallelisiert mit PVM

PVM (Parallel Virtual Machine) ist eine Bibliothek für Unixe Maschinen, die es ermöglicht über das Netzwerk verteilte Anwendungen zu parallelisieren. Und was eignet sich besser zum Demonstrieren als die Berechnung eines Apfelmännchens (Mandelbrotmenge).

// written by André Betz 
// http://www.andrebetz.de


#include <stdio.h>
#include <stdlib.h>
#include "pvm3.h"
#define  MSGLEN  200
#define  MANUELL 5

typedef struct Datas
{
  int      Start;
  int      Length;
  int      px;
  int      py;
  int      DimX;
  int      DimY;
  char     tp;
  double   X1Re;
  double   X2Re;
  double   Y1Im;
  double   Y2Im;
  double   CR;
  double   CI;
  unsigned long StopIter;
  double   Range;
} *pDatas,xDatas;

unsigned long Julia(pDatas pPos)
{
  unsigned long Iter = 0;
  double Re,Im;
  double Di = 0.0;
  double ZR = 0.0;
  double ZI = 0.0;
  double pR = pPos->X1Re + (pPos->X2Re - pPos->X1Re)/pPos->DimX * pPos->px;
  double pI = pPos->Y1Im + (pPos->Y2Im - pPos->Y1Im)/pPos->DimY * pPos->py;

  if(pPos->tp=='j')
  {
    ZR = pR;
    ZI = pI;
  }
  if(pPos->tp=='m')
  {
    pPos->CR = pR;
    pPos->CI = pI;
  }

  while((Iter<=pPos->StopIter)&&(Di<=(pPos->Range*pPos->Range)))
  {
    Re = ZR*ZR - ZI*ZI + pPos->CR;
    Im = 2*ZR*ZI + pPos->CI;
    Di = Re*Re + Im*Im;
    ZR = Re;
    ZI = Im;
    Iter++;
  }

  return Iter;
}

void child(int tid_my,int tid_parent)
{
  xDatas Pos;
  int count,z;
  long pixel;
  unsigned long *Buf;
  char *Msg;

  pvm_recv(tid_parent,1);     
  pvm_upkbyte((char*)&Pos,sizeof(struct Datas),1);

  Msg = (char*)malloc(MSGLEN);
  Buf = (unsigned long*)malloc(sizeof(unsigned long) * Pos.Length);
  
  sprintf(Msg,"t%x bearbeitet Pixel von %d bis %d\n",tid_my,Pos.Start,Pos.Start+Pos.Length);
  pvm_initsend(PvmDataDefault);
  pvm_pkstr(Msg);
  pvm_send(tid_parent,1);
 
  for(count=0;count<Pos.Length;count++)
  {
    pixel =  Pos.Start + count;
    Pos.px = pixel % Pos.DimX;
    Pos.py = pixel / Pos.DimX;
    z = Julia(&Pos);
    Buf[count] = z;
  }

  pvm_initsend(PvmDataDefault);
  pvm_pkbyte((char*)&Pos,sizeof(struct Datas),1);
  pvm_send(tid_parent,1);

  pvm_initsend(PvmDataDefault);
  pvm_pkbyte((char*)Buf,sizeof(unsigned long) * Pos.Length,1);
  pvm_send(tid_parent,1);

  free(Buf);
  free(Msg);
}

void Split(xDatas Pos,char* Pic,char* Datei)
{
  int  z,r,g,b;
  int  run;
  long PixPart;
  long PixRest;
  long pixel;
  long count;
  int  *tid_childs;
  unsigned long *Buf;
  char *Msg;
  struct pvmhostinfo *hostp;
  int narch;
  int parts;

#ifdef MANUELL
  parts = MANUELL;
#else
  info = pvm_config(&parts,&narch,&hostp);
#endif
    
  pixel   = Pos.DimX * Pos.DimY;
  PixPart = pixel / parts;
  PixRest = pixel % parts;

  tid_childs = (int*)malloc(sizeof(int)*parts);
  Buf        = (unsigned long*)malloc(sizeof(unsigned long) * (PixPart+PixRest));
  Msg        = (char*)malloc(MSGLEN);
  
  pvm_spawn(Datei,(char**)0,PvmTaskDefault,"",parts,tid_childs);

  printf("Rechnung ist in %d Teile aufgespalten\n",parts);

  for(run=0;run<parts;run++)
  {
#ifndef MANUELL
    printf("Starten von t%x auf %s\n",tid_childs[run],hostp[run].hi_name);
#endif
    
    Pos.Start   = PixPart * run;
    Pos.Length  = PixPart;
    if((pixel - Pos.Start)<2*PixPart) Pos.Length  = PixPart + PixRest;

    pvm_initsend(PvmDataDefault);
    pvm_pkbyte((char*)&Pos,sizeof(struct Datas),1);
    pvm_send(tid_childs[run],1);

    pvm_recv(tid_childs[run],1);
    pvm_upkstr(Msg);
    printf(Msg);
  }

  printf("Warte auf Rückmeldung\n");

  for(run=0;run<parts;run++)
  {
    pvm_recv(tid_childs[run],1);
    pvm_upkbyte((char*)&Pos,sizeof(struct Datas),1);
    
    pvm_recv(tid_childs[run],1);
    pvm_upkbyte((char*)Buf,sizeof(unsigned long) * Pos.Length,1);

    printf("Daten von t%x erhalten\n",tid_childs[run]);
    for(count=0;count<Pos.Length;count++)
    {
      pixel = Pos.Start + count;
      z = Buf[count]; 
      z = (unsigned long)((double)16777216 * (double)Pos.StopIter / (double)z);
      Pic[pixel*3]   = (z & 0x00FF0000) >> 16;
      Pic[pixel*3+1] = (z & 0x0000FF00) >> 8;
      Pic[pixel*3+2] = z & 0x000000FF;
    }
  }

  free(tid_childs);
  free(Buf);
  free(Msg);
}

int main(int argc,char **argv)
{
  FILE *InputFile;
  FILE *PicFile;
  char *Pic;
  xDatas Pos;
  int tid_my;
  int tid_parent;
  int pvm_err;
  int parts;

  tid_my     = pvm_mytid();
  tid_parent = pvm_parent();

  if(tid_parent == PvmNoParent)
  {
    if(argc!=3)
    {
      printf("Type: m\n");
      printf("DimX: 400\n");
      printf("DimY: 400\n");
      printf("MinRe: -2\n");
      printf("MaxRe: 1\n");
      printf("MinIm: -1\n");
      printf("MaxIm: 1\n");
      printf("CR: 0.5\n");
      printf("CI: 0.5\n");
      printf("Tiefe: 200\n");
      pvm_exit();
      exit(1);
    }
  
    InputFile = fopen(argv[1],"r");
    fscanf(InputFile,"Type: %c\n",  &(Pos.tp));  
    fscanf(InputFile,"DimX: %d\n",  &(Pos.DimX));
    fscanf(InputFile,"DimY: %d\n",  &(Pos.DimY));
    fscanf(InputFile,"MinRe: %lf\n",&(Pos.X1Re));
    fscanf(InputFile,"MaxRe: %lf\n",&(Pos.X2Re));
    fscanf(InputFile,"MinIm: %lf\n",&(Pos.Y1Im));
    fscanf(InputFile,"MaxIm: %lf\n",&(Pos.Y2Im));
    fscanf(InputFile,"CR: %lf\n",   &(Pos.CR));
    fscanf(InputFile,"CI: %lf\n",   &(Pos.CI));
    fscanf(InputFile,"Tiefe: %d\n", &(Pos.StopIter));
    Pos.Range = 2;
    fclose(InputFile);

    Pic = (char*)malloc(Pos.DimX*Pos.DimY*3);  
    Split(Pos,Pic,argv[0]);

    PicFile = fopen(argv[2],"w");
    fprintf(PicFile,"P6\n");
    fprintf(PicFile,"%d %d\n",Pos.DimX,Pos.DimY);
    fprintf(PicFile,"%d\n",255);
    fwrite(Pic,Pos.DimX*Pos.DimY*3,1,PicFile);
    fclose(PicFile);
    free(Pic);
  }
  else
  {
    child(tid_my,tid_parent);
  }

  pvm_exit();
}

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.