Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Tobiking

1x Rätselkönig

  • Private Nachricht senden

11

28.06.2012, 13:15

Ich finde ein paar Behauptungen hier echt komisch. Zum Beispiel verstehe ich nicht was an lokalen Variablen so schlimm sein soll. In vielen Fällen sorgt der Compiler einfach dafür, dass der Wert solange er benötigt wird in einem Register bleibt. Das verbraucht genau 0 Speicherplatz und ist die schnellstmögliche Lösung. Generell sind Compiler sehr effizient was das Verteilen von Variablen auf Registern oder das Berücksichtigen von Caches angeht. Da muss man schon viel Aufwand betreiben und Wissen mitbringen um das von Hand zu überbieten.

Das 1/3 mehr Code auch 1/3 mehr Rechenzeit braucht ist auch ziemlich an den Haaren herbeigezogen. Inzwischen haben moderne Prozessoren so viele Recheneinheiten, dass sie viele Befehle gleichzeitig ausführen können. Da lässt sich kaum noch eine Aussage über die Dauer einzelner Befehle machen. Das Einzige was man da noch mit Sicherheit sagen kann ist, dass Befehle mit Datenabhängigkeit der Reihe nach ausgeführt werden müssen, und daher prinzipiell länger brauchen, und dass Speicherzugriffe wahnsinnig langsam sind, falls der angeforderter Wert nicht schon im Cache liegt. Der erste Punkt wird wieder vom Compiler ziemlich gut erledigt. Aber zumindest der zweite Punkt lässt sich auch in Hochsprachen berücksichtigen und hat neben der erwähnten Optimierung der Algorithmen den größten Effekt.

CBenni::O

1x Contest-Sieger

Beiträge: 1 145

Wohnort: Stuttgart

  • Private Nachricht senden

12

28.06.2012, 17:03

Umm... Junge.
Was passiert denn mit

Quellcode

1
Fkt_A(Fkt_B(Fkt_C(42)));

?
Der Compiler mach daraus (höstwarscheinlich) sowas: (in Pseudocode)

Quellcode

1
2
3
eax = Fkt_C(42);
eax = Fkt_B(eax);
eax = Fkt_A(eax);

wo ist da der zusätzliche Speicherverbrauch einer lokalen Variablen?

mfg CBenni::O
Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.
42!
Aufräumen kann jeder, nur das Genie überblickt das Chaos!
Metal will never die!
1. Sppro Gamecontest - mein Beitrag

13

28.06.2012, 18:28

"Nö, wir entwickeln nichts besseres, wir bauen nur noch den alten Quark, kauft den und seid zufrieden.". Aber selbst das ginge nicht, weil man die alte Hardware natürlich oft parallel betreiben kann und damit automatisch wieder ein besseres System selbst erschafft, für welches die Software-Entwicklung dann abzielt und die Hardware-Entwickler nachziehen müssen.
Es ist also kein "Der User muss kaufen, weil die Industrie immer bessere Hardware herstellt", sondern es ist ein Kreislauf, bei welchem *jeder*, sowohl der User, als auch die Entwickler und Hardware-Hersteller stets nachziehen müssen. Es rennt also niemand voraus, sondern alle laufen sich im Kreis hinterher und werden automatisch schneller. Das geht gar nicht anders.
Das würde sich auch nicht ändern, wenn "mehr Leute ihre Programme optimieren" würden. Denn auch dann wäre eine mittelmäßige Hardware einer guten unterlegen und der User wäre damit irgendwann nicht mehr zufrieden und würde umsteigen. Außerdem ist auch mal irgendwo Schluss mit Optimierung. Gerade AAA-Games müssen sehr gut optimiert sein, weil sie sonst oft nicht mal auf mittelmäßiger Hardware überhaupt laufen würden.


Natürlich wäre eine mittelmäßige Hardware einer guten dann immernoch unterlegen aber je besser das ganze optimiert wird, desto länger die mittelmäßige Hardware und es müssen nicht schonwieder Resourcen zum Bau einer neuen Hardware ausgegeben werden. Außerdem möchte ich dich mal daran errinern, dass wir irgendwann an die physikalischen Grenzen stoßen werden und so lange wird das nicht mehr dauern.

Mal ein bisschen Stoff zum lesen:
http://www.storyal.de/story-2011/pc-technik.html

KKrieger verschwendet haufenweise RAM. Nur mal so nebenbei. Und so schön prozedurale Erstellung von Texturen und Sounds auch ist (nur so wurde es so klein), so lässt sich auf Dauer nicht produktiv Software oder gar Spiele entwickeln, die den Qualitätsansprüchen genügt. Generierte Texturen und Sounds werden nie das sein, was Grafiker oder Tonstudios produzieren können. Weder von der Geschwindigkeit der Herstellung, noch der Qualität.
Das ist mir klar, KKrieger war aber auch als Beispiel für niedrigen Festplattenspeicherplatz gedacht, also verdrehe hier bitte nichts.
Ja. Weil die Adresse nicht durch 4 teilbar ist, wird das Laden der Daten schonmal langsamer, z.B. Caching spielt hier rein. Wenn Du dann noch anfängst und aus jedem Laden einer Variable nicht 2 Takte, sondern 8 zu machen... ja nee, is sicher schneller. Pipelining kannste hier dann auch komplett in die Tonne treten, Du musst die Daten ja seriell aufbereiten. Das kann gar nicht schneller sein als mit Alignment. Nie im Leben.
Letztendlich ist es aber ein Abwägen zwischen RAM Verbrauch und Prozessorauslastung. Wenn man Variablen in Structs gleich korrekt ausrichten würde, dann werden sie auch nicht viel größer, auch mit Alignment, schließlich bleiben 4 ein Byte große Variablen in einem Struct auch immernoch 4 ein Byte große Variablen und werden eben nicht auf 16 Byte aufgepumpt, auch nicht mit data alignment.
Erklär mir bitte, warum man dann Pipelining in die Tonne treten kann.
Falsch. Mehr Code heißt nicht weniger Effizienz. Manchmal ist genau das Gegenteil der Fall. Wichtig sind hier Stichworte wie "Pipelining" und "Taktzeiten". Das kennt der Compiler prima, Du aber nicht. Nie im Leben wirst Du heute noch mit eigenem ASM-Code den VC-Compiler schlagen, wenn ihr beide die selbe Aufgabe vorgesetzt bekommt. Auf keinen Fall. Das galt früher mal, zu Pascal-Zeiten, aber heute nicht mehr. Ich zweifle sogar an, dass Du auch nur ansatzweise die heutigen Register alle kennst. AH und AL... man, das ist 15 Jahre her... Und da hat sich in der Architektur aber SEHR viel getan!
Oh man, wenn du willst kann ich dir den diassemblierten Code gerne schicken, da will ich mal sehen wie das bitte erklären möchtest, das daran so ultra "effizient" ist, jeder andere der den Code gesehen hat, den der Compiler da ausgespuckt hat, hat sich darüber gewundert wie dermaßen ineffektiv er ist. Die Floating Point Number Register und der ganze Rest etc. interessieren mich relativ wenig, da ich sie damals für meine Arbeit nicht benötigt hatte und auch erstmal nicht für zukünfte Arbeiten benötige, damals ging es um ROM Hacking und da waren außer EAX, ECX, EDX, EBP und ESP keine anderen Register von Bedeutung, möchtest du mir jetzt unterstellen nur weil ich keine Ahnung von den zahlreichen anderen Registern in modernen Prozessoren habe, habe ich generell von dem Thema keine Ahnung? Übrigens sind alle AMD64 Prozessoren in der Lage ihre Register im 32-bit Modus und sogar im 16-Modus ansprechbar, heißt also AX existiert noch, bei AH und AL bin ich mir nicht so sicher, dass diese nicht mehr großartig genutzt worden sind seit es Windows NT gibt ist mir schon klar.
Mal ganz davon abgesehen, vielleicht 2MB an Verwaltungsdaten im RAM einzusparen bringt genau was, wenn man Sounds und Texturen verwendet, die mehrere hundert MB groß sind? Genau, gar nichts außer Performance-Verlust durch fehlendes Alignment.
Kommt ganz drauf an was man für ein Spiel programmieren möchte, ich glaube kaum, dass es bei heutigen Spielen die mal eben 2 GB RAM verschlingen nur 2 MB an Verwaltungsdaten sind die man einsparen könnte. Dennoch ist es etwas aus dem Kontext gegriffen, da ich ein solches Spiel nicht programmiere. Es ist aber richtig, dass Sounds und Texturen wohl den größten Teil beanspruchen.
PS: Ich habe bis in MMX2-Zeiten hinein sehr viel mit Assembler entwickelt, ich weiß also, worüber ich hier rede!

5 Jahre ROM Hacking und ein bisschen 65x02 Assembler auf dem NES sowie 80x86 Assembler auf DOS Ebene.

Zum ersten: Wenn ich in einem Bewerbungsgespräch hören würde das jemand für allen Code so vorgeht, würde ich ihn Fragen wie gut er es schafft Release Termine einzuhalten. Besonders das du pauschal für allen Code von Anfang so vorgehst lässt bei mir in dem Punkt Entwicklungstempo die Alarmglocken schrillen.

Wieso das? Ich frage mich wie du meinst, dass man für soetwas tatsächlich so lange brauchen kann? Ich muss nicht lange überlegen, bevor ich mich für einen Datentyp entscheide. Wenn man darin Übung hat ist das eine Sache von wenigen Sekunden. Und erzähl mir bitte nicht, die aufsummierten 5 bis 20 Minuten die sich daraus vielleicht ergeben würden, wären dermaßen relevant.
Der Compiler wird das mit den Shifts oder der Benutzung von AH und AL machen, wenn du ihn mit einem Packing von 1 dazu zwingst. Wobei AL und AH nur mit chars ginge. Bei Shorts kommst du nur an den unteren Short über AX schnell ran. Den oberen Teil musst du dir aus EAX rausshiften.
Belege das bitte, wenn du dir nicht sicher bist.
Und in der Tat ja, das Shiften wird die Performance mehr behindern als der Speichermehrverbrauch, ausser deine Performance ist wirklich ganz krass memory bound! Aber das sollte man nicht als Schuss ins blaue annehmen von daher ist das kein Fehler des Compilers sondern eine Performanceoptimierung die der Compiler für dich durchführt!

Du vergisst aber, dass bei heutigen Spielen das meiste die GPU übernimmt, außerdem gibt es mit Sicherheit noch andere Wege als reines Bitshifting.
Und Performance in der Zahl der Instruktionen messen zu wollen ist sehr gefährlich. Nicht alle Instruktionen benötigen die selbe Anzahl an Taktzyklen.

Das ist mir klar aber die meisten benötigen 1 oder 2 Takte, gerade die, über die ich als Beispiel geredet habe.
Und die optimale Speicherausnutzung gegen Ende der DOS Ära hat noch einen anderen Grund gehabt, der sich in der Tat erledigt hat: RAM war knapp und teuer. Da mag man zwar von halten was man will, aber der Punkt hat sich mittlerweile erledigt. Man sollte nur nicht mit dem Speicher so asen, dass das Interface CPU <-> RAM zum Bottleneck wird. Und da ist der erste und einfachste Punkt: Das Alignment beachten, damit die CPU effizient aus dem RAM laden kann.

Du vergisst dass wir auch irgendwann an einem Punkt angelangen, wo wir durch physikalische Gesetze beschränkt werden, irgendwann müssen wir anfangen zu optimieren, das gilt im aber Moment mehr für CPUs als für RAM. Dennoch, allein schon aus Ökologischer Sicht ist es pure Resourcen Verschwendung, die da betrieben wird.
Ich finde ein paar Behauptungen hier echt komisch. Zum Beispiel verstehe ich nicht was an lokalen Variablen so schlimm sein soll.

Siehe das Beispiel von unten, es ist einfach unnötig.
Das 1/3 mehr Code auch 1/3 mehr Rechenzeit braucht ist auch ziemlich an den Haaren herbeigezogen. Inzwischen haben moderne Prozessoren so viele Recheneinheiten, dass sie viele Befehle gleichzeitig ausführen können. Da lässt sich kaum noch eine Aussage über die Dauer einzelner Befehle machen. Das Einzige was man da noch mit Sicherheit sagen kann ist, dass Befehle mit Datenabhängigkeit der Reihe nach ausgeführt werden müssen, und daher prinzipiell länger brauchen, und dass Speicherzugriffe wahnsinnig langsam sind, falls der angeforderter Wert nicht schon im Cache liegt. Der erste Punkt wird wieder vom Compiler ziemlich gut erledigt. Aber zumindest der zweite Punkt lässt sich auch in Hochsprachen berücksichtigen und hat neben der erwähnten Optimierung der Algorithmen den größten Effekt.
Äh, ja klar. Aber das ständige hin und hergeschiebe des [ebp+0008] in verschiedene Register zum Zugriff auf ein Array, wobei es doch viel sinnvoller wäre immer nur eins zu benutzen, soll die CPU nicht bremsen und Speicherplatz verschwenden oder wie? Es handelt sich hierbei um einen Prozess der nur einen einzigen Thread hat. Desweiteren ist es egal wieviele Befehle sie gleichzeitig ausführen können, 1/3 Befehle zuviel, sind 1/3 Befehle die ohne Sinn ausgeführt werden und selbst wenn der Prozessor mehrere gleichzeitig ausführen könnte, kann er es in diesem Prozess eben nicht, weil es wichtig ist, dass die Befehle hintereinander abgearbeitet werden.
Umm... Junge.
Was passiert denn mit

Quellcode

1
Fkt_A(Fkt_B(Fkt_C(42)));

?
Der Compiler mach daraus (höstwarscheinlich) sowas: (in Pseudocode)

Quellcode

1
2
3
eax = Fkt_C(42);
eax = Fkt_B(eax);
eax = Fkt_A(eax);

wo ist da der zusätzliche Speicherverbrauch einer lokalen Variablen?

mfg CBenni::O
Es gibt eben keinen, wo verwendest du da bitte lokale Variablen? Ich sehe keine. Ich redete von solchem Code:

C-/C++-Quelltext

1
2
3
4
5
6
int a;
int b;
int c;
a = Fkt_A(42);
b = Fkt_B(a);
c = Fkt_C(b);


Unzwar ohne, dass a und b nochmal später im Code verwendet werden.

CBenni::O

1x Contest-Sieger

Beiträge: 1 145

Wohnort: Stuttgart

  • Private Nachricht senden

14

28.06.2012, 18:40

Auch dieser Code kommt aufs selbe raus ;) Compiler sind ZIEMLICH gut geworden.
Es gibt kaum Optimierungen im Codestil selbst (microcode) die sich noch auf den fertigen Code auswirken.

mfg CBenni::O
Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.
42!
Aufräumen kann jeder, nur das Genie überblickt das Chaos!
Metal will never die!
1. Sppro Gamecontest - mein Beitrag

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

15

28.06.2012, 18:43

Zum ersten: Wenn ich in einem Bewerbungsgespräch hören würde das jemand für allen Code so vorgeht, würde ich ihn Fragen wie gut er es schafft Release Termine einzuhalten. Besonders das du pauschal für allen Code von Anfang so vorgehst lässt bei mir in dem Punkt Entwicklungstempo die Alarmglocken schrillen.

Wieso das? Ich frage mich wie du meinst, dass man für soetwas tatsächlich so lange brauchen kann? Ich muss nicht lange überlegen, bevor ich mich für einen Datentyp entscheide. Wenn man darin Übung hat ist das eine Sache von wenigen Sekunden. Und erzähl mir bitte nicht, die aufsummierten 5 bis 20 Minuten die sich daraus vielleicht ergeben würden, wären dermaßen relevant.
Der Compiler wird das mit den Shifts oder der Benutzung von AH und AL machen, wenn du ihn mit einem Packing von 1 dazu zwingst. Wobei AL und AH nur mit chars ginge. Bei Shorts kommst du nur an den unteren Short über AX schnell ran. Den oberen Teil musst du dir aus EAX rausshiften.
Belege das bitte, wenn du dir nicht sicher bist.
Und in der Tat ja, das Shiften wird die Performance mehr behindern als der Speichermehrverbrauch, ausser deine Performance ist wirklich ganz krass memory bound! Aber das sollte man nicht als Schuss ins blaue annehmen von daher ist das kein Fehler des Compilers sondern eine Performanceoptimierung die der Compiler für dich durchführt!

Du vergisst aber, dass bei heutigen Spielen das meiste die GPU übernimmt, außerdem gibt es mit Sicherheit noch andere Wege als reines Bitshifting.
Zum 1: Das was du nennst ist aufwendig. Nicht unbedingt das Datentyp auswählen, mehr das möglichst große vermeiden von lokalen Variablen. Und insbesondere muss ich dabei auch anmerken, das klingt auch nicht nach sehr gut lesbarem Code.

Zum 2: http://css.csail.mit.edu/6.858/2011/readings/i386.pdf, Figure 2-5 auf Seite 31. Es gibt EAX, dann AX für den unteren Teil, der sich dann in AH und AL unterteilt. Wie du selbst sagtest, hat sich dort ja nicht viel getan. Ausser vielleicht bei x64 natürlich, wo aber eher noch was wegfallen sein dürfte.

Zum 3: Es gibt noch andere Wege als Bitshifting? Belege bitte!

Edit:

Zitat

Äh, ja klar. Aber das ständige hin und hergeschiebe des [ebp+0008] in
verschiedene Register zum Zugriff auf ein Array, wobei es doch viel
sinnvoller wäre immer nur eins zu benutzen, soll die CPU nicht bremsen
und Speicherplatz verschwenden oder wie?


In der Tat wird das die CPU nicht wirklich bremsen, den obersten Teil vom Stack wirste nahezu sicher im L1-Cache haben. Allein schon weil du oft Funktionen aufrufen wirst.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

16

28.06.2012, 18:45

Die Floating Point Number Register und der ganze Rest etc. interessieren mich relativ wenig, da ich sie damals für meine Arbeit nicht benötigt hatte und auch erstmal nicht für zukünfte Arbeiten benötige,

Zeiten ändern sich. Was damals effizient war, kann heute auf eine andere Art noch viel effizienter gehen.

Ich muss zugeben, von den ganzen hardcore Optimierungen habe ich relativ wenig Ahnung - wozu auch, die braucht man heute eh fast nie. Aber ich weiß, dass die Hersteller da Ahnung von haben und wenn die sagen, Alignment lohnt sich, dann wird das auch fast immer so sein. Und wenn man es verhindert, wird man fast immer Nachteile haben.

Zitat

Außerdem möchte ich dich mal daran errinern, dass wir irgendwann an die physikalischen Grenzen stoßen werden und so lange wird das nicht mehr dauern.
Naja, dann wird halt dann optimiert. Aber es ist doch so: Wieso sollte ich ein halbes Jahr Arbeit darein stecken, meine Engine 10% schneller zu machen, wenn in einem halben Jahr die Durchschnittliche Hardware 15% schneller ist? Wovon die hochoptimierte Version allerdings wenig hat, da die alten Optimierungen auf der neuen Hardware nicht mehr greifen.

Letztendlich stimmt es natürlich, dass das neue Word auf neuen Rechnern genauso lange zum Starten braucht, wie das erste Word auf den uralt Rechnern. Aber ist das wirklich ein Problem? Es ist ja nicht so, dass man die alte Hardware jetzt um ein vielfaches billiger bauen könnte. Und die Preise für Bürotaugliche PCs fallen kontinuierlich. Wo Leistung im Überfluss ist, kann man keine Verschwenden.
Lieber dumm fragen, als dumm bleiben!

Tobiking

1x Rätselkönig

  • Private Nachricht senden

17

28.06.2012, 19:31

Äh, ja klar. Aber das ständige hin und hergeschiebe des [ebp+0008] in verschiedene Register zum Zugriff auf ein Array, wobei es doch viel sinnvoller wäre immer nur eins zu benutzen, soll die CPU nicht bremsen und Speicherplatz verschwenden oder wie?

Was für ein Array? In ebp wird die Adresse des Stacks gespeichert. Mit [ebp+0008] lässt sich sparsam eine Stelle auf dem Stack ansprechen. Würde man absolute Adressen nutzen, wären die Maschinenbefehle länger. Und den Stack verwendet man für Funktionsparameter (Je nach Aufrufkonvention erst wenn es zu viele sind). Hinterher muss man dafür sorgen das der Stack wieder vor die Parameter zeigt. Das tut man in Assembler nicht anders. Du könntest natürlich auf Funktionen verzichten. Damit bläst du aber deine Executable auf, was du ja auch nicht willst.

Es handelt sich hierbei um einen Prozess der nur einen einzigen Thread hat. Desweiteren ist es egal wieviele Befehle sie gleichzeitig ausführen können, 1/3 Befehle zuviel, sind 1/3 Befehle die ohne Sinn ausgeführt werden und selbst wenn der Prozessor mehrere gleichzeitig ausführen könnte, kann er es in diesem Prozess eben nicht, weil es wichtig ist, dass die Befehle hintereinander abgearbeitet werden.

Ich habe genau diese Antwort erwartet. Es hat rein gar nichts mit multithreading zu tun. Der Prozessor führt intern die Befehle parallel aus. Siehe http://de.wikipedia.org/wiki/Superskalarit%C3%A4t. Ich vertrau deiner Aussage, dass die Befehle hinternander ausgeführt werden müssen auch nicht so richtig. Es gibt so viele Techniken, wie Register Renaiming, Out of Order Execution und die erwähnte Superskalarität, dass wie schon gesagt es nahezu unmöglich ist Voraussagen zu treffen.

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

18

28.06.2012, 19:53

Übrigens möchte ich nicht schreiben bitshifts seien so teuer und mov vom stack so billig. Bin aber Grad am Handy.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

19

28.06.2012, 19:57

Ohne Klassen? Wenige/keine lokalen Variablen? Rein modulare Programmierung?
Wenn dieser ganze Kram so ineffizient und langsam ist, warum wurde er dann erfunden?

Ich glaube du machst dir zu viele Gedanken über Dinge die heute nicht mehr von Bedeutung sind. Gerade Speicherverbrauch ist nahezu Wurst. Auch 100MB RAM jucken kaum noch jemanden in Zeiten in denen 4GB RAM Untergrenze sind.

Ich würde gerne mal Code von dir sehen, nicht nur irgendwas aus dem Kontext gegriffenes, sondern vielleicht eine cpp Datei. Irgendwas wo du glaubst ernsthaft Resourcen und Performance gespart zu haben. Viel schreiben kann ich nicht, da ich mich nicht mit der Architektur von heute auskenne (ich kenne z.B. den 6502), aber das meiste wurde ja schon gesagt.

20

28.06.2012, 20:48

Zitat

Auch dieser Code kommt aufs selbe raus ;) Compiler sind ZIEMLICH gut geworden.
Es gibt kaum Optimierungen im Codestil selbst (microcode) die sich noch auf den fertigen Code auswirken.

mfg CBenni::O


Beleg bitte? :)

Zum 1: Das was du nennst ist aufwendig. Nicht unbedingt das Datentyp auswählen, mehr das möglichst große vermeiden von lokalen Variablen. Und insbesondere muss ich dabei auch anmerken, das klingt auch nicht nach sehr gut lesbarem Code.


Was auch nicht weiter schlimm ist, denn ich möchte ja Code schreiben, den ich möglichst danach nicht wieder groß anfassen muss damit ich ihn ohne großes Umschreiben wiederverwenden kann. Wenn ich irgendwann mal etwas verbessern muss oder etwas verändern muss, empfiehlt es sich sowieso den Code nochmal ganz neu zu schreiben, da man erfahrungsgemäß sich dann sowieso einen besseren Codingstil angewöhnt hat und etwas mehr weiß.
Ich habe auch kein Problem damit lokale Variablen zu vermeiden, hab es mir gleich von Anfang an angewöhnt und ich brauche auch nicht länger als wenn ich sie benutze und wenn kein Weg daran vorbei führt und es sich nunmal anbietet weil es wesentlich einfacher ist, benutze ich sie ohnehin.
Wenn man mit anderen arbeitet, ist das alles sowieso nochmal eine ganz andere Geschichte, dann einigt man sich auf einen Codingstil aber im Moment arbeite ich alleine und werde es wohl auch weiterhin, also kann es mir völlig egal sein. Deshalb weiß ich auch nicht wo das Problem liegt, außer, dass du mir nicht glaubst, dass ich ohne lokale Variablen auch nicht viel länger brauche.


Zum 2: Zum 3: Es gibt noch andere Wege als Bitshifting? Belege bitte!


Bitte genauer lesen, ich habe geschrieben "mit Sicherheit", ich habe nicht gesagt, dass ich welche kenne. Spontan würde mir da nur div einfallen, aber der Befehl ist sicher langsamer als Bitshift und Modulo, wobei ich nichtmal weiß, ob ein Modulo ohne div möglich ist. Div würde zumindest zwei Fliegen mit einer Klappe schlagen, falls man Zugriff auf beide Variablen brauch, da beide Variablen schonmal in zwei verschiedenen Registern gespeichert sind.

In der Tat wird das die CPU nicht wirklich bremsen, den obersten Teil vom Stack wirste nahezu sicher im L1-Cache haben. Allein schon weil du oft Funktionen aufrufen wirst.


Es geht nicht um den obersten Teil vom Stack, es geht um eine Funktion, bei der bekannterweis folgender Code ausgeführt wird:

Quellcode

1
2
push ebp
mov ebp, esp


Wenn der Basepointer nun zig mal in verschiedene Register gespeichert wird, ist es immernoch Verschwendung, egal wie gering sie auch sein mag. Und letztendlich sind es nur Mutmaßungen die hier geäussert werden, Fakt ist aber das die Verschwendung nicht von der Hand zu weisen ist.

Ich muss zugeben, von den ganzen hardcore Optimierungen habe ich relativ wenig Ahnung - wozu auch, die braucht man heute eh fast nie. Aber ich weiß, dass die Hersteller da Ahnung von haben und wenn die sagen, Alignment lohnt sich, dann wird das auch fast immer so sein. Und wenn man es verhindert, wird man fast immer Nachteile haben.


Die vergisst aber auch, dass die Hersteller unbedingt ihr Zeug verkaufen wollen oder glaubst du alles aus der Werbung? Gibt so einige CPUs die vom Hersteller hoch angepriesen sind dann aber im Benchmark Test plötzlich nicht mehr so gut abschneiden.

Naja, dann wird halt dann optimiert. Aber es ist doch so: Wieso sollte ich ein halbes Jahr Arbeit darein stecken, meine Engine 10% schneller zu machen, wenn in einem halben Jahr die Durchschnittliche Hardware 15% schneller ist? Wovon die hochoptimierte Version allerdings wenig hat, da die alten Optimierungen auf der neuen Hardware nicht mehr greifen.


Es macht aber nichts sich im Vorfeld darum schonmal Gedanken zu machen und es gibt auch Optimierungen die auf jeder Hardware laufen und nicht nur speziell für eine Hardware gemacht werden müssen.

Aber ist das wirklich ein Problem? Es ist ja nicht so, dass man die alte Hardware jetzt um ein vielfaches billiger bauen könnte. Und die Preise für Bürotaugliche PCs fallen kontinuierlich. Wo Leistung im Überfluss ist, kann man keine Verschwenden.


Du vergisst aber dass Herstellung, Vertrieb und vorallem auch Betrieb Unmengen an Energie fressen. Alte Hardware braucht kommt oft mit wesentlich weniger aus. Und Leistung ist eben nicht im Überfluss vorhanden, wir haben heutzutage ziemliche Probleme was Energie anbelangt. (Stichwort: Atomkraft)
Guck dir mal an, wie das digitale Verbindungen wie HDMI etc. machen, da wird aus "Urheberrechtlichen Gründen" tausende Signale verschlüsselt, entschüsselt, verschlüsselt, entschlüsselt, verschlüsselt und so weiter. Wenn du da noch Adapter ranklatscht, dann ist der übermäßige Stromverbrauch perfekt, alles zur Last der Verbraucher.

Was für ein Array? In ebp wird die Adresse des Stacks gespeichert. Mit [ebp+0008] lässt sich sparsam eine Stelle auf dem Stack ansprechen. Würde man absolute Adressen nutzen, wären die Maschinenbefehle länger. Und den Stack verwendet man für Funktionsparameter (Je nach Aufrufkonvention erst wenn es zu viele sind). Hinterher muss man dafür sorgen das der Stack wieder vor die Parameter zeigt. Das tut man in Assembler nicht anders. Du könntest natürlich auf Funktionen verzichten. Damit bläst du aber deine Executable auf, was du ja auch nicht willst.


[ebp+0008] zeigt auf die erste Variable im struct Array, die besagten Funktionen, von denen ich schon die ganze Zeit rede sind ziemlich schlecht optimiert.
Du verstehst nicht was ich meine, ich rede z.B. von folgendem Code:

mov eax, [ebp+0008]
mov ecx, [eax+000C]
add ecx, 00002000
mov edx, [ebp+0008]
mov [edx+000C], ecx

Die zweite Fett markierte Instruktion ist völlig überflüssig, selbst wenn der Prozessor diese parallel ausführen könnte, willst du mir doch nicht ernsthaft erzählen, dass sich daraus irgendein Nutzen ergibt außer Strom zu verbrauchen? Da gibts auch noch wesentlich bessere Kracher:

mov edx, [ebp+0008]
mov eax, [edx+0078]
add eax, 01
mov ecx, [ebp+0008]
mov [ecx+0078], eax
mov edx, [ebp+0008]
cmp dword ptr [edx+0078], 08

Und das sind noch nette Beispiele, da gibts noch viel schlimmeres Zeug, wenn man das alles entfernen würde und per Hand noch einige Optimierungen vornehmen würde, würde die exe Datei wesentlich kleiner werden und das Programm schneller laufen.

Warum willst du eingendlich keine Pointer benutzen? Das ist doch genau der Sinn davon.


Weil sie umständlich zu benutzen sind und es mit vorgefertigten Klassen in C++ zumindest tausend mal einfacher geht.

Mal davon abgesehn hat Objektorientierung doch so gravierende Vorteile, dass ich deine Verbohrtheit in prozenduale Programmierung überhaupt nicht verstehen kann. Komme selbst aus dem Mikrocontrollerbereich und bin nur zu froh Assembler und C nicht mehr sehen zu müssen. Beim DSP würd ichs verstehn aber warum beim PC?


Wieso Verbohrtheit? Ich benutze objektorintierte Programmierung nicht, wo ich sie nicht benötige, wo ist das Problem? Nur weil du es einfacher findest mit Klassen und Objekten zu arbeiten, heißt das nicht, dass ich es genauso sehe. Und ich kenne beide Seiten, habe ich aber auch schonmal geschrieben. Aber es ist schön wieviele hier meinen Wunsch, den ich zu Anfang des Threads gestellt hatte, nämlich nicht in eine Offtopic Diskussion zu entgleiten respektiert haben.

Und übrigens: http://de.wikipedia.org/wiki/Objektorien…Grenzen_der_OOP

Ohne Klassen? Wenige/keine lokalen Variablen? Rein modulare Programmierung?


Prozedurale Programmierung, fast reines C, hab ich aber auch schon geschrieben, lies dir bitte meine Posts durch voher durch. ;)

Wenn dieser ganze Kram so ineffizient und langsam ist, warum wurde er dann erfunden?


Weil Leute irgendwann Probleme hatten, bei riesigen Projekten noch die Übersicht zu behalten und die Effizienz aller Teammitglieder sicher zu stellen. Ich arbeite aber alleine.

Ich glaube du machst dir zu viele Gedanken über Dinge die heute nicht mehr von Bedeutung sind. Gerade Speicherverbrauch ist nahezu Wurst. Auch 100MB RAM jucken kaum noch jemanden in Zeiten in denen 4GB RAM Untergrenze sind.


Diese Dinge sind immernoch von Bedeutung, zumindest für mich, es ist schade, dass nicht mehr auf Resourcen geachtet wird, diese Zeiten werden aber irgendwann vorbei sein und das wird auch nicht mehr lange auf sich warten lassen.

Ich würde gerne mal Code von dir sehen, nicht nur irgendwas aus dem Kontext gegriffenes, sondern vielleicht eine cpp Datei. Irgendwas wo du glaubst ernsthaft Resourcen und Performance gespart zu haben. Viel schreiben kann ich nicht, da ich mich nicht mit der Architektur von heute auskenne (ich kenne z.B. den 6502), aber das meiste wurde ja schon gesagt.


Gerne, allerdings spare ich nur "von Grund auf", größere Optimierungen habe ich bis jetzt noch an keinem Programm vorgenommen, da ich einfach zu oft "umgestiegen" bin und "neugeschrieben" habe, wenn mir etwas nicht gepasst hat. Schlussendlich bin ich aber doch bei C++ gelandet, wenn ich es vor 2 Jahren vielleicht noch nicht geglaubt habe. Wenn ich bald den Rendering Teil meines Programmes fertig habe, kann ich dir gerne etwas zeigen.

Werbeanzeige