Page 1 sur 1

L'enfer du typage

Publié : mer. 30/déc./2009 11:02
par ker2x
Coucou, j'ai codé une appli pour faire un rendu de Buddhabrot.
http://ker.endofinternet.net/img/ (fait avec une version java)
J'ai eu 50.000 bugs de typage de variable... maintenant "ca marche", mais c'est vraiment degueulasse et y'a encore des bugs qui traine.
(la variable "dodraw" par exemple, je passe que 0 ou 1, mais je retrouve 0 ou 28905 dans ma procedure iterate)

A noter que je suis en 64bits avec PureBasic 4.40 (x64)

Voila le code, que j'essaye de nettoyer :

Code : Tout sélectionner

Global screenSize = 800
Global bailout = 1000
Global plots = 1000
Global maxexposure = 0
Global time = 0
Global exposures = 0
Global drawing = 0  ; 0 = false ; 1 = true

Global Dim exposure(screenSize*screenSize)

For i = 0 To screenSize*screenSize
  exposure(i) = 1
  ;Debug exposure(i)
Next i

Structure Pixel
  Pixel.l
EndStructure

Procedure iterate(x0.d, y0.d, dodraw)
  x.f = 0.0
  y.f = 0.0
  xnew.f = 0.0
  ynew.f = 0.0
  ix = 0
  iy = 0
  
  For i = 0 To bailout
    xnew.f = x.f * x.f - y.f * y.f + x0
    ynew.f = 2 * x.f * y.f + y0
    If ((dodraw.i <> 0) And (i > 0))
      ix = Int(screenSize * (xnew.f + 1.5) / 2.0)
      iy = Int(screenSize * (ynew.f + 1) / 2.0)
      If ((ix>= 0) And (iy >= 0) And (ix < screenSize) And (iy < screenSize))
        exposure(ix*screenSize+iy) = exposure(ix*screenSize+iy) + 1
      EndIf
    EndIf
    
    If ((xnew*xnew + ynew*ynew) > 4)
      ;Debug 1
      ProcedureReturn 1
    EndIf
    x.f = xnew.f
    y.f = ynew.f
  Next i
  ;Debug 0
  ProcedureReturn 0
EndProcedure

Procedure plotPlots(plots.i)
  x0.d = 0
  y0.d = 0
  For k = 0 To plots
    x0.d = Random(10000000)/10000000.0 *3.0 - 2.0
    ;Debug x0
    y0.d = Random(10000000)/10000000.0 *3.0 - 1.5
    ;Debug y0
    If(iterate(x0.d,y0.d,0) = 1)
      iterate(x0.d,y0.d,1)
      exposures = exposures + 1
    EndIf
  Next k
EndProcedure



Procedure findMaxExposure()
  maxexposure = 0
  For i = 0 To screenSize*screenSize
    If (exposure(i) > maxexposure)
      maxexposure = exposure(i)
    EndIf
  Next i
EndProcedure


; initialize the sprite engine
If InitSprite() = 0
  MessageRequester("Error", "Can't open screen & sprite enviroment!", 0)
  End
EndIf

; open window
If OpenWindow(0, 0, 0, screenSize, screenSize, "Buddhabrot", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If OpenWindowedScreen(WindowID(0), 0, 0, screenSize, screenSize, 0, 0, 0, #PB_Screen_NoSynchronization)
    ;If StartDrawing(ScreenOutput())
      ;Buffer      = DrawingBuffer()             ; Get the start address of the screen buffer
      ;Pitch       = DrawingBufferPitch()        ; Get the length (in byte) took by one horizontal line
      ;PixelFormat = DrawingBufferPixelFormat()  ; Get the pixel format. 
    ;  StopDrawing()
  ;  EndIf
  Else
    MessageRequester("Error", "Can't open windowed screen!", 0)
    End
  EndIf
EndIf

Repeat
  Repeat
    Event = WindowEvent()
    Select Event 
      Case #PB_Event_CloseWindow
        End 
    EndSelect
  Until Event = 0

  plotPlots(plots)
  time = time +1
  If ((time % 30) = 0)
    findMaxExposure()
    StartDrawing(ScreenOutput())
    CreateImage(0,screenSize,screenSize)
    For x = 0 To screenSize -1
      For y = 0 To ScreenSize - 1
        ramp.d = exposure(x*screenSize+y) / (maxexposure / 2.5)
        If (ramp.d > 1)
          ramp.d = 1
        EndIf
        ;Debug ramp
        Plot(x,y,RGB(ramp*255.0,ramp*255.0,ramp*255.0))
      Next y
    Next x
    StopDrawing()
  EndIf

  FlipBuffers() 
  ;ClearScreen(RGB(0, 0, 0))
ForEver
Si vous pouviez m'aider a clarifier tout ca (et m'assurer que j'ai tout bien en precision maxi, au passage), ca serait vraiment, vraiment chic :)

J'ai passé une partie de la nuit dessus, alors c'est pas joli-joli.
Le but derriere sera d'optimiser le code a mort, mais d'abord faut que ca soit clean :mrgreen:
Merci !

Re: L'enfer du typage

Publié : mer. 30/déc./2009 14:29
par djes
Magnifique! En laissant tourner le programme, l'image semble se "nettoyer" d'elle-même.

Re: L'enfer du typage

Publié : mer. 30/déc./2009 15:07
par Ar-S
En effet c'est super joli bravo :!:

Re: L'enfer du typage

Publié : mer. 30/déc./2009 16:30
par djes
J'ai bidouillé rapidement (je dois partir), mais c'est pas encore ça

Code : Tout sélectionner

Global screenSize = 800
Global bailout = 1000
Global plots = 1000
Global maxexposure.d = 0
Global time = 0
Global exposures = 0
Global drawing = 0  ; 0 = false ; 1 = true

Global Dim exposure.d(screenSize, screenSize)

For u = 0 To screenSize
  For i = 0 To screenSize
	  exposure(u,i) = 1
	;Debug exposure(i)
  Next i
Next u

Structure Pixel
	Pixel.l
EndStructure

Procedure iterate(x0.d, y0.d, dodraw)
	x.d = 0.0
	y.d = 0.0
	xnew.d = 0.0
	ynew.d = 0.0
	ix.d = 0
	iy.d = 0
	
	For i = 0 To bailout
		xnew = x * x - y * y + x0
		ynew = 2 * x * y     + y0
		If ((dodraw <> 0) And (i > 0))
			ix = (xnew + 1.5) * screenSize * 0.5
			iy = (ynew + 1.0) * screenSize * 0.5
			If ((ix >= 0) And (iy >= 0) And (ix < screenSize) And (iy < screenSize))
				exposure(Int(ix), Int(iy)) = exposure(Int(ix),Int(iy)) + 1
			EndIf
		EndIf
		
		If ((xnew*xnew + ynew*ynew) > 4)
			;Debug 1
			ProcedureReturn 1
		EndIf
		x = xnew
		y = ynew
	Next i
	;Debug 0
	ProcedureReturn 0
EndProcedure

Procedure plotPlots(plots.i)
	x0.d = 0
	y0.d = 0
	For k = 0 To plots
		x0.d = - 2.0 + (Random(30000000)/10000000.0); * 3.0
		;Debug x0
		y0.d = - 1.5 + (Random(30000000)/10000000.0) ;* 3.0 
		;Debug y0
		If(iterate(x0.d,y0.d,0) = 1)
			iterate(x0.d,y0.d,1)
			exposures = exposures + 1
		EndIf
	Next k
EndProcedure



Procedure findMaxExposure()
	maxexposure = 0
	For u = 0 To screenSize
	  For i = 0 To screenSize
		  If (exposure(i,u) > maxexposure)
			  maxexposure = exposure(i,u)
		  EndIf
	  Next i
  Next u
EndProcedure


; initialize the sprite engine
If InitSprite() = 0
	MessageRequester("Error", "Can't open screen & sprite enviroment!", 0)
	End
EndIf

; open window
If OpenWindow(0, 0, 0, screenSize, screenSize, "Buddhabrot", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	If OpenWindowedScreen(WindowID(0), 0, 0, screenSize, screenSize, 0, 0, 0, #PB_Screen_NoSynchronization)
		;If StartDrawing(ScreenOutput())
			;Buffer      = DrawingBuffer()             ; Get the start address of the screen buffer
			;Pitch       = DrawingBufferPitch()        ; Get the length (in byte) took by one horizontal line
			;PixelFormat = DrawingBufferPixelFormat()  ; Get the pixel format. 
		;  StopDrawing()
	;  EndIf
	Else
		MessageRequester("Error", "Can't open windowed screen!", 0)
		End
	EndIf
EndIf

Repeat
	Repeat
		Event = WindowEvent()
		Select Event 
			Case #PB_Event_CloseWindow
				End 
		EndSelect
	Until Event = 0

	plotPlots(plots)
	time = time +1
	If ((time % 30) = 0)
		findMaxExposure()
		StartDrawing(ScreenOutput())
		CreateImage(0,screenSize,screenSize)
		For x = 0 To screenSize -1
			For y = 0 To ScreenSize - 1
				ramp.d = exposure(x,y) / (maxexposure / 2.5)
				If (ramp.d > 1)
					ramp.d = 1
				EndIf
				;Debug ramp
				Plot(x,y,RGB(ramp*255.0,ramp*255.0,ramp*255.0))
			Next y
		Next x
		StopDrawing()
	EndIf

	FlipBuffers() 
	;ClearScreen(RGB(0, 0, 0))
ForEver

Re: L'enfer du typage

Publié : mer. 30/déc./2009 16:52
par GallyHC
Bonjour,

Le resultat est bien sympa, il faut surement encore d'ameliore mais deja un tres bon debut.

Cordialement,
GallyHC

PS: tu peu mettre ta source sur mon site si tu le desire URL=http://www.koakdesign.info/?url=04, faut juste que tu creer ton compte.

Re: L'enfer du typage

Publié : mer. 30/déc./2009 17:09
par ker2x
La prochaine etape, une fois tout beau tout propre, c'est la couleur :)

http://www.superliminal.com/fractals/bbrot/bbrot.htm

Re: L'enfer du typage

Publié : jeu. 31/déc./2009 15:17
par ker2x
J'ai rajouté d'autres images, et le code source : http://ker.endofinternet.net/img/

Je me demande si je fais un portage en C++ ou pas...
La version purebasic est deja un portage d'une version java :)

La version pb est plus rapide que celle en java, c'est deja un bon point.
Il faudrait que je multithread mais c'est pas facile et le gain n'est pas evident.

Quand a une version openCL/GPGPU c'est encore moins gagné car chaque iteration demande un acces a l'ensemble de la carte des orbites, ce qui n'est pas le cas d'un rendu de mandelbrot normal ou chaque point est completement independant...

Re: L'enfer du typage

Publié : ven. 01/janv./2010 21:08
par ker2x
J'ai resolu mes soucis.
Et ajouté la couleur :)

Code : Tout sélectionner

;
; Buddhabrot generator
; By Laurent "ker2x" Laborde
; 31/12/2009 - Version 1
;
; PureBasic 4.40

EnableExplicit

; Generate Assembler code
RunProgram(#PB_Compiler_Home+"\Compilers\pbcompiler.exe",  Chr(34)+ "F:\purebasic\buddhabrot\main.pb" + Chr(34) + " /COMMENTED /SSE2 /EXE " + Chr(34)+ "F:\purebasic\buddhaexe" +Chr(34) , "", #PB_Program_Open|#PB_Program_Read|#PB_Program_Hide)

; Define constant
#screenSize = 512
#screenSize2 = (#screenSize * #screenSize)
#bailout =  1000
;
#bailoutRmin = 0
#bailoutRmax = 1000
;
#bailoutBmin = 0
#bailoutBmax = 500

#bailoutGmin = 0
#bailoutGmax = 50
;
;
#miniter = 0
#plots = 1000000
#RandMax = 2147483647 
#RandMaxBy4 = 536870911
;
; Define global var
Global.q maxexposure = 0
Global.q maxexposureR = 0
Global.q maxexposureG = 0
Global.q maxexposureB = 0
;
Global.q exposures = 0
Global.q performance = 0
;
Global.q Dim exposureR(#screenSize2)
Global.q Dim exposureG(#screenSize2)
Global.q Dim exposureB(#screenSize2)
;
Structure ExposureStruct
  R.q
  G.q
  B.q
EndStructure
;
Global Dim exposure.ExposureStruct(#screenSize2)
;
; 
;
; Pointer stuff, unused
;Define *exposure = @exposure(0)
;
; Check if point is in Mandelbrot Set
Procedure isInMSet(x0.d, y0.d)
  Define.d x ;= 0.0
  Define.d y ;= 0.0
  Define.d xnew ;= 0.0
  Define.d ynew ;= 0.0
  Define.i i
  
  For i = 0 To #bailout
    exposures = exposures + 1
    xnew = (x * x) - (y * y) + x0
    ynew = 2 * (x*y) + y0
    If ((xnew*xnew + ynew*ynew) > 4)
      ProcedureReturn 0
    EndIf
    x = xnew
    y = ynew
  Next i
  ProcedureReturn 1
EndProcedure

; Iterate and draw the orbit
Procedure iterate(x0.d, y0.d)

  Define.d x ;= 0.0
  Define.d y ;= 0.0
  Define.d xnew ;= 0.0
  Define.d ynew ;= 0.0
  Define.i ix ;= 0
  Define.i iy ;= 0
  Define.i i
  
  For i = 0 To #bailout
    exposures = exposures + 1
    xnew = (x * x) - (y * y) + x0
    ynew = 2 * (x*y) + y0
    If ((i > #miniter))
      ix = Int(#screenSize * (xnew.d + 2.250) / 4.0)
      iy = Int(#screenSize * (ynew.d + 2.0) / 4.0)
      If ((ix >= 0) And (iy >= 0) And (ix < #screenSize) And (iy < #screenSize))
        Define.q pos = ix*#screenSize+iy
        If ((i < #bailoutRmax) And (i > #bailoutRmin))
          exposure(pos)\R = exposure(pos)\R +1
        EndIf
        If ((i < #bailoutGmax) And (i > #bailoutGmin))
          exposure(pos)\G = exposure(pos)\G +1
        EndIf
        If ((i < #bailoutBmax) And (i > #bailoutBmin))
          exposure(pos)\B = exposure(pos)\B +1
        EndIf
      EndIf
    EndIf
    
    If ((xnew*xnew + ynew*ynew) > 4)
      ProcedureReturn 1
    EndIf
    x = xnew
    y = ynew
  Next i
  
  ProcedureReturn 0
EndProcedure

; Find the max exposure point
Procedure findMaxExposure()
  ;maxexposure = 0
  Define.i i
  For i = 0 To #screenSize2
    If (exposure(i)\R > maxexposureR)
      maxexposureR = exposure(i)\R
    EndIf
    If (exposure(i)\G > maxexposureG)
      maxexposureG = exposure(i)\G
    EndIf
    If (exposure(i)\B > maxexposureB)
      maxexposureB = exposure(i)\B
    EndIf
  Next i
EndProcedure

; MAIN
; initialize the sprite engine
If InitSprite() = 0
  MessageRequester("Error", "Can't open screen & sprite enviroment!", 0)
  End
EndIf

; open window
If OpenWindow(0, 0, 0, #screenSize, #screenSize, "Buddhabrot", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If OpenWindowedScreen(WindowID(0), 0, 0, #screenSize, #screenSize, 0, 0, 0, #PB_Screen_NoSynchronization)
    ;If StartDrawing(ScreenOutput())
      ;Buffer      = DrawingBuffer()             ; Get the start address of the screen buffer
      ;Pitch       = DrawingBufferPitch()        ; Get the length (in byte) took by one horizontal line
      ;PixelFormat = DrawingBufferPixelFormat()  ; Get the pixel format. 
    ;  StopDrawing()
  ;  EndIf
  Else
    MessageRequester("Error", "Can't open windowed screen!", 0)
    End
  EndIf
EndIf

; Local var
Define.q Event
Define.q k
Define.q x
Define.q y

Define.d x0
Define.d y0
Define.d ramp
Define.d rampR
Define.d rampG
Define.d rampB
Define.q StartTime = ElapsedMilliseconds() 

Repeat
  Repeat
    Event = WindowEvent()
    Select Event 
      Case #PB_Event_CloseWindow
        End 
    EndSelect
  Until Event = 0

  ;plotPlots(#plots)
  x0 = 0
  y0 = 0
  For k = 0 To #plots
    x0 = (Random(#RandMax)/(#RandMaxBy4)) - 2.0
    y0 = (Random(#RandMax)/(#RandMaxBy4)) - 2.0
    If(isInMSet(x0,y0) = 0)
      iterate(x0,y0)
    EndIf
  Next k
  
  
  findMaxExposure()
  StartDrawing(ScreenOutput())
  CreateImage(0,#screenSize,#screenSize)
  For x = 0 To #screenSize -1
    For y = 0 To #screenSize - 1
      Define.q pos = x*#screenSize+y
      rampR = exposure(pos)\R / (maxexposureR / 2.5)
      rampG = exposure(pos)\G / (maxexposureG / 2.5)
      rampB = exposure(pos)\B / (maxexposureB / 2.5)

      If (rampR > 1)
        rampR = 1
      EndIf
      If (rampG > 1)
        rampG = 1
      EndIf
      If (rampB > 1)
        rampB = 1
      EndIf
  
      Plot(y,x,RGB(rampR*255.0,rampG*255.0,rampB*255.0))
    Next y
  Next x
  performance =  exposures / (ElapsedMilliseconds() - StartTime) 
  DrawText(0,0, "Bailout : " + Str(#bailout) + "   million Iterations : " + Str(exposures / 1000000.0) + "    iterations/ms : " + Str(performance), RGB(255,255,255))
  StopDrawing()

  FlipBuffers() 
  ;ClearScreen(RGB(0, 0, 0))
ForEver




Re: L'enfer du typage

Publié : ven. 01/janv./2010 21:12
par ker2x
- 56600 iterations/ms sur mon Q6600
- 74000 iterations/ms sur le Core i7 d'une amie

Et vous, combien ? :)

Re: L'enfer du typage

Publié : sam. 02/janv./2010 1:23
par djes
28403 sur un athlon 2400 (en remplaçant le type quad de x,y,k par de l'integer)
Superbe!

Re: L'enfer du typage

Publié : sam. 02/janv./2010 5:10
par ker2x
djes a écrit :28403 sur un athlon 2400 (en remplaçant le type quad de x,y,k par de l'integer)
Superbe!
Merci :)
Je code pour du 64bits oui.
Et j'espere arriver a faire de l'optimisation assembleur SSE3

Pour l'instant je suis plongé dans les doc de reference Intel, c'est du lourd.

Edit : et l'algo aussi. Dans le code au dessus j'ai trouvé pas mal de truc a ameliorer coté algo... surtout en lisant le code assembleur :)

Re: L'enfer du typage

Publié : sam. 02/janv./2010 7:41
par ker2x
Image

Re: L'enfer du typage

Publié : sam. 02/janv./2010 18:49
par comtois
bon boulot c'est magnifique.