C ------ a_master.f ---------------------------------- 1997...2001 ---- C M.Pester C asynchrone Mandelbrot-Version: Master-Prozess C teilt das Gebiet in Rechtecke auf, versendet deren C Koordinaten und Parameter aus dem Nutzerdialog an C die Slaves, zeichnet die zurückgelieferten Farbwerte C ======== subroutine a_master(A,w,h,Quiet) include 'include/trnet.inc' include 'farmnet.inc' include 'include/Grafics.inc' Integer Nslave,w,h,A(*) Integer ncol(2),NUL(2) Integer BlockID(5,MAXPROC) ! js,jp,nh,nw (receive) Logical ProcActive(MAXPROC) DOUBLE PRECISION X0,X1,Y0,Y1,dX,dY,x,y,XJ,YJ,XXJ,YYJ Logical JULIA,JJulia,Quiet,asynchron,Yes COMMON /daten/ x,y,dX,dY,XXJ,YYJ,JJulia,nw,nh COMMON /aktuell/ X0,X1,Y0,Y1,XJ,YJ,ITMAX,JULIA DATA NUL /0,0/ Nslave=NPROC-1 ! alle außer ICH sind Slaves Nslice=MAX(8,NPROC/2) ! horizontale Streifen XXJ=XJ YYJ=YJ JJulia=JULIA dX=(X1-X0)/w dY=(Y1-Y0)/h C Aufteilung des Gebietes auf Nslave Prozessoren nw0 = w / (Nslave) if ( MOD(w,Nslave) .GT. 0 .AND. (nw0+1)*(Nslave-1) .LT. w ) + nw0=nw0+1 nw1 = w-(Nslave-1)*nw0 ! letzter Prozessor nimmt den Rest nh0 = h/Nslice ! Unterteilungen in der Hoehe if ( MOD(h,Nslice) .GT. 0 .AND. + (nh0+1)*(Nslice-1) .LT. h) nh0=nh0+1 nh1 = h-nh0*(Nslice-1) ! letzte Schicht meist etwas duenner C Raster ausgeben: call gsetforeground(han,icolor(0)) ix=w-1 iy=h-1 DO i=1,Nslave-1 call gdrawline(han,i*nw0,0,i*nw0,iy) ENDDO DO i=1,Nslice-1 call gdrawline(han,0,i*nh0,ix,i*nh0) ENDDO call gsync asynchron=Yes('Asynchrone Kommunikation verwenden') write(*,*) 'Pixelaufloesung' write(*,*) ' dx,dy:',dX,dY write(*,*) 'max. Iterationszahl: ',ITMAX write(*,'(A,$)') 'Berechnung ... ' call ATree_Down_0(1,ITMAX) call gRaiseWin(han) call Init_Time c Farbindex 1 für Hintergrund (bei ITMAX) c ncol(1) = Index der ersten Farbe aus Farbtabelle c ncol(2) = Anzahl verwendeter Farben (modulo) if (ncolmax .GT. 70) then ncol(1) = ncolmax-4 ncol(2) = 4 else if (ncolmax .GT. 1) then ncol(1) = ncolmax-1 ncol(2) = 1 else ncol(1) = 2 ncol(2) = 0 endif C erste Blockzeile verteilen: y=Y0 nh=nh0 nw=nw0 DO jp = 1,NPROC-1 x=X0+(jp-1)*nw0*dX if (jp .EQ. NPROC-1) nw=nw1 call Send_Async_0(2,ncol,jp) call Send_Async_0(15,X,jp) call SetBlock(BlockID(1,jp),1,jp,nh,nw) ProcActive(jp)=.TRUE. ENDDO jA=1 nBL=0 nxt=1 ! reihum jeweils alle Prozessoren abfragen DO js=2,Nslice+1 C ! Parameter fuer naechstes Senden, fragt sich nur noch, an wen y = Y0 + (js-1)*nh0*dY DO jp = 1,Nslave x = X0 + (jp-1)*nw0*dX nw=nw0 if (jp .EQ. Nslave) nw=nw1 C ! loop through the slaves to find one ready: DO WHILE ( (Info_Async_0(nxt) .GT. 0 .AND. asynchron) .OR. + .NOT. ProcActive(nxt) ) nxt=nxt+1 if (nxt .GT. Nslave) nxt=1 ENDDO C ! now get data from slave nxt call Recv_Async_0(1,BlockID(5,nxt),nxt) call GetBlock(BlockID(1,nxt),iy0,ix0,nh2,nw2) if (Quiet) jA=jA+4 call Recv_Async_0(nh2*nw2,A(jA),nxt) iy0=(iy0-1)*nh0 ix0=(ix0-1)*nw0 if (Quiet) then A(jA-4)=ix0 A(jA-3)=iy0 A(jA-2)=nw2 A(jA-1)=nh2 jA=jA + nw2*nh2 nBL=nBL+1 endif if (js .LE. Nslice) then ! neue Schicht in Auftrag geben C ! dieser Prozessor (nxt) erhaelt den naechsten Auftrag nh=nh0 if (js .EQ. Nslice) nh=nh1 call Send_Async_0(2,ncol,nxt) call Send_Async_0(15,X,nxt) call SetBlock(BlockID(1,nxt),js,jp,nh,nw) else call Send_Async_0(2,NUL,nxt) ProcActive(nxt)=.FALSE. ! Prozessor "angehalten" endif C ! zeichnen, was empfangen wurde if (.NOT. Quiet) call dsplrect(ix0,iy0,nw2,nh2,A) nxt=nxt+1 if (nxt .GT. Nslave) nxt=1 ENDDO ! jp ENDDO ! js call Get_Times(A(jA)) write(*,'(A/A,$)') ' beendet.', ' Zeitdiagramm - ' call Write_Times(A(jA)) call Time_Graf(A(jA)) if (Quiet) then jA=1 DO js=1,nBL call dsplrect(A(jA),A(jA+1),A(jA+2),A(jA+3),A(jA+4)) jA=jA + 4 + A(jA+2)*A(jA+3) ENDDO endif return END C ----- subroutine SetBlock(BlockID,js,jp,nh,nw) Integer BlockID(4),js,jp,nh,nw BlockID(1)=js BlockID(2)=jp BlockID(3)=nh BlockID(4)=nw return end C ----- subroutine GetBlock(BlockID,js,jp,nh,nw) Integer BlockID(4),js,jp,nh,nw js=BlockID(1) jp=BlockID(2) nh=BlockID(3) nw=BlockID(4) return end