Warum ist das 2 .Programm als EXE fast 19mal so groß.

Für allgemeine Fragen zur Programmierung mit PureBasic.
funkheld
Beiträge: 636
Registriert: 31.12.2009 11:58

Warum ist das 2 .Programm als EXE fast 19mal so groß.

Beitrag von funkheld »

Warum ist das 2 .Programm als EXE fast 19mal so groß.
Purebasic 5.6

Danke.
Gruss

77000 Byte groß als EXE :

Code: Alles auswählen

Global buffer.l,pitch.l,PixelFormat.l,zaehler.l

Enumeration
  #Window_0
  #canv
EndEnumeration

OpenWindow(#window_0, 10,10, 500,500, "Canvas")
CanvasGadget(#canv, 10, 10, 400, 400)

StartDrawing(CanvasOutput(#canv))
  buffer = DrawingBuffer() 

  !MOV ebx,dword [v_buffer]

  !MOV ecx,160000 
  !nextbyte:
  !MOV dword [ebx],$00ff00
  !add ebx,3
  !dec ecx
  !TEST ecx, ecx
  !JNZ  nextbyte
StopDrawing()
  
 Repeat
  Event = WaitWindowEvent()    
  
  Select Event
    Case #PB_Event_Gadget
      EventGadget = EventGadget()
      
      EventType = EventType
        Case #PB_Event_CloseWindow
      EventWindow = EventWindow()
      If EventWindow = #Window_0
        CloseWindow(#Window_0)
        Break
      EndIf
  EndSelect 
ForEver

1500000 Byte groß als EXE :

Code: Alles auswählen

Global buffer.l,pitch.l,PixelFormat.l,zaehler.l

Enumeration
  #Window_0
  #canv
EndEnumeration

OpenWindow(#window_0, 10,10, 500,500, "Canvas")
CanvasGadget(#canv, 10, 10, 400, 400)

StartDrawing(CanvasOutput(#canv))
  buffer = DrawingBuffer() 

  !MOV ebx,dword [v_buffer]

  !Repeat 160000 
    !MOV dword [ebx],$ff0000
    !add ebx,3
  !End Repeat
StopDrawing()
  
 Repeat
  Event = WaitWindowEvent()    
  
  Select Event
    Case #PB_Event_Gadget
      EventGadget = EventGadget()
      
      EventType = EventType
        Case #PB_Event_CloseWindow
      EventWindow = EventWindow()
      If EventWindow = #Window_0
        CloseWindow(#Window_0)
        Break
      EndIf
  EndSelect
ForEver
Benutzeravatar
TroaX
Beiträge: 659
Registriert: 08.03.2013 14:27
Computerausstattung: PC: Ryzen 9 3950X, 96 GB RAM, RX6800XT, 2.5 TB SSD, 21:9 Display, Pop_OS! | Lappi: Ryzen 7 5800H, 16 GB RAM, 1 TB SSD, Pop_OS!
Wohnort: NRW
Kontaktdaten:

Re: Warum ist das 2 .Programm als EXE fast 19mal so groß.

Beitrag von TroaX »

Ich würde mal folgendes vermuten: https://flatassembler.net/docs.php?article=ufasm

Zitat von der verlinkten Seite:

Code: Alles auswählen

repeat 5
	add	eax,eax
end repeat
This time the directive of the assembler is used to repeat the instruction five times. But no jumping is done here. What assembler generates when meets the above construct, is actually the same what would be generated when we wrote it this way:

Code: Alles auswählen

        add     eax,eax
	add	eax,eax
	add	eax,eax
	add	eax,eax
	add	eax,eax
Assembler generates the five copies of the same machine instruction.
PureBasic nutzt FASM und ich denke in der Executable steht bei dir in Maschinencode jetzt 160.000 mal direkt hintereinander:

Code: Alles auswählen

!MOV dword [ebx],$ff0000
!add ebx,3
Das summiert sich natürlich ;)
PC: Ryzen 9 3950X | 96 GB RAM | RX6800XT | 2,5 TB NVMe | Pop_OS!
Notebook: 16" 3:2 | Ryzen 7 5800H | 16 GB RAM | Radeon Vega | 1TB NVMe | Pop_OS!
NAS: Fritz.Box :lol:
Coding: Purebasic 6.04 | PHP | HTML | CSS | Javascript
funkheld
Beiträge: 636
Registriert: 31.12.2009 11:58

Re: Warum ist das 2 .Programm als EXE fast 19mal so groß.

Beitrag von funkheld »

Na....da wird ja dann ein Mist hergestellt.

Gruss
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Warum ist das 2 .Programm als EXE fast 19mal so groß.

Beitrag von STARGÅTE »

Nun ja, es gibt nun mal immer das Zusammenspiel zwischen Ausführungszeit und Speicherverbrauch.
Durch das direkte wiederholen des Befehls gewinnst du halt die Zeit die sonst beim vermindern des Schleifenregisters benötigt wird, dafür wird jedoch mehr Speicher benötig, um den nun immer wiederkehrenden Befehl zu speichern.
Vor allem der Sprungbefehl ist (im vergleich zu einfachen Operationen) recht langsam.
Solche Optimierungen machen jedoch nur dann sinn, wenn sich die Schleife unveränderlich ist.
In deinem Fall wären dann die Exe immer nur für eine Bildgröße nützlich.

Die Frage die sich hier stellt ist, wie schnell ist denn der längere Code?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
funkheld
Beiträge: 636
Registriert: 31.12.2009 11:58

Re: Warum ist das 2 .Programm als EXE fast 19mal so groß.

Beitrag von funkheld »

Der längere Code braucht mehr Zeit bei meinem Programm.
Deine Aussage hat bei dem Purebasic-ASM kein Wert.

Kannst selber Testen um deine Aussage zu festigen.

Gruss
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Warum ist das 2 .Programm als EXE fast 19mal so groß.

Beitrag von NicTheQuick »

Wenn der Code nicht komplett in den Cache passt, dann braucht er natürlich länger. Häufige Wiederholungen mit conditional JUMPs sollten heute auch dank Branchprediction und Konsorten gar nicht mehr viel ausmachen.

Dass dein Code aufgebläht wird, liegt ja offenbar daran, dass der repeat-Befehl unter fasm ein Makro ist und der dementsprechend den Code so häufig wiederholt wie angegeben. In diesen Dimensionen stelle ich mir das nicht sinnvoll vor. Der Befehle ist sicherlich nur dafür da ein bisschen Schreibarbeit zu sparen und dabei Copy&Paste-Fehler zu vermeiden.

Aber eine Kombination aus beidem stelle ich mir sinnvoll vor. Weniger Schleifendurchläufe und mehr Instruktionen pro Durchlauf.
Bild
funkheld
Beiträge: 636
Registriert: 31.12.2009 11:58

Re: Warum ist das 2 .Programm als EXE fast 19mal so groß.

Beitrag von funkheld »

Ist sicherlich blöd, das ein Macro in dieser Dimension wiederholt in ASM eingesetzt wird.

Also totaler Blödsinn im Assembler oder ein fehlerhaftes Verhalten im Assembler ???

Gruss
DarkDragon
Beiträge: 6267
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: Warum ist das 2 .Programm als EXE fast 19mal so groß.

Beitrag von DarkDragon »

Computer arbeiten nach der Von-Neumann-Architektur, die besagt, dass sowohl der Programmcode als auch die Daten im selben Speicher gehalten werden. Für uns ist das der RAM. Von dort aus zieht der Prozessor sich Blockweise die Befehle in den Cache (Speicher auf dem Prozessor) und dort werden die dann nacheinander abgearbeitet. Für jeden Befehl benötigt der Prozessor eine gewisse Zeit (Taktzyklen).

Dein erster Code sieht nun so aus:

Code: Alles auswählen

  !MOV ecx,160000 
  !nextbyte:
  !MOV dword [ebx],$00ff00
  !add ebx,3
  !dec ecx
  !TEST ecx, ecx
  !JNZ  nextbyte
Wenn du vorher weißt, dass du den Code fixe 160000 Mal ausführst, ist das ineffizient. Besser du machst folgendes und halbierst die Anzahl der DEC, TEST, JNZ Befehle für die jeweils eine gewisse Zeit drauf ginge:

Code: Alles auswählen

  !MOV ecx,80000 
  !nextbyte:
  !MOV dword [ebx],$00ff00
  !add ebx,3
  !MOV dword [ebx],$00ff00
  !add ebx,3
  !dec ecx
  !TEST ecx, ecx
  !JNZ  nextbyte
Noch besser wäre es, du viertelst die Schleife:

Code: Alles auswählen

  !MOV ecx,40000 
  !nextbyte:
  !MOV dword [ebx],$00ff00
  !add ebx,3
  !MOV dword [ebx],$00ff00
  !add ebx,3
  !MOV dword [ebx],$00ff00
  !add ebx,3
  !MOV dword [ebx],$00ff00
  !add ebx,3
  !dec ecx
  !TEST ecx, ecx
  !JNZ  nextbyte
Usw.

Allerdings kommen wir irgendwann an einen Punkt, da passt dieser Codeblock nicht mehr in den Cache des Prozessors, da die in der Regel recht klein sind (Faustregel: je kleiner die Art des Speichers, desto schneller). Dann muss der Prozessor Codestücke nachladen aus dem RAM und das dauert wieder länger. Deshalb ist dein zweiter Code eventuell doch nicht so schnell.

Desweiteren kommt noch hinzu, dass deine Schleife nicht unbedingt dort anfängt wo es optimal für den Prozessor wäre, da er quasi gerne Blöcke holt, die beim Byte a*2^b anfangen. Das kann man z.B. durch den Präprozessorbefehl !ALIGN X sicherstellen. Und wenn du Sprünge im Code hast kommt eventuell noch der Prefetcher durcheinander und muss andere Codeblöcke "vorhersagen", aber das trifft hier m.E.n. nicht zu.

Wenn du Prozessoren kaufst also immer darauf achten, dass genügend L1/L2/L3 Cache vorhanden ist und nicht immer nur auf die Taktrate starren :wink: .
funkheld hat geschrieben:Ist sicherlich blöd, das ein Macro in dieser Dimension wiederholt in ASM eingesetzt wird.

Also totaler Blödsinn im Assembler oder ein fehlerhaftes Verhalten im Assembler ???
Bitte halte doch nicht immer gleich alles für blöd oder doof wenn du es nicht ganz verstehst. Du kommst damit sehr überheblich rüber. Diese drei "???" üben Druck auf die Antwortenden aus und sind alles andere als nett.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Antworten