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