L'enfer du typage

Programmation d'applications complexes
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

L'enfer du typage

Message 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 !
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: L'enfer du typage

Message par djes »

Magnifique! En laissant tourner le programme, l'image semble se "nettoyer" d'elle-même.
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: L'enfer du typage

Message par Ar-S »

En effet c'est super joli bravo :!:
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: L'enfer du typage

Message 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
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

Re: L'enfer du typage

Message 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.
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: L'enfer du typage

Message par ker2x »

La prochaine etape, une fois tout beau tout propre, c'est la couleur :)

http://www.superliminal.com/fractals/bbrot/bbrot.htm
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: L'enfer du typage

Message 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...
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: L'enfer du typage

Message 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



ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: L'enfer du typage

Message par ker2x »

- 56600 iterations/ms sur mon Q6600
- 74000 iterations/ms sur le Core i7 d'une amie

Et vous, combien ? :)
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: L'enfer du typage

Message par djes »

28403 sur un athlon 2400 (en remplaçant le type quad de x,y,k par de l'integer)
Superbe!
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: L'enfer du typage

Message 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 :)
ker2x
Messages : 61
Inscription : dim. 11/mai/2008 7:27

Re: L'enfer du typage

Message par ker2x »

Image
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: L'enfer du typage

Message par comtois »

bon boulot c'est magnifique.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Répondre