Hallo, ich habe im PICmicro-Hochsprachenbuch gelesen, dass Compiler einen nicht optimalen Code erstellen (obwohl manche 2300 Euro kosten). Gibt es da so etwas wie einen Nachoptimmierer, der das erstellte ASM-File in seiner Funktionsweise analysiert und anschließend das optimale ASM-File generiert? So könnte man jeden billigen Compiler und jede Hochsprache verwenden und hätte immer die maximal mögliche Performance.
Es ist genau umgekehrt: Ein C-Compiler kann seinen Code mehr oder weniger optimieren, aber nur aus dem C-Code raus. Ein gcc optimiert z.B. deutlich besser als ich es in Assembler könnte - was allerdings nicht viel heisst :-) Allerdings baut er auch etwas an Overhead ein, den man beim händischen programmieren einsparen könnte. Du solltest dir mal eine Assemblerausgabe von einem C-Compiler ansehen, da ist nicht mehr viel rauszuholen.
Hallo Stefan Das gute an einer Hochsprache ist doch dass Sie einfach ist und man sehr schnell Programmieren kann. Das hat natürlich den Nachteil dass der Code nicht immer optimal ist. Du willst den Fünfer und das Brötchen. Anders gefragt braucht man einen Opimierten code? Ich sage mal relativ selten wenn es um geschwindigkeit geseht eherer wenn es um Speicherplatz geht. Das einfachste ist du schreibst den Code mit einer Hochsprache und lässt in in Assebler übersetzen und dann optimiert du den code von Hand. Gruss Pimmelmann
Hallo, ergänzend hierzu hätte ich folgende Frage bzw. Handoptimierung. Angenommen ich habe folgene Funktion mit inlines: void Test(void) { bla... bla... asm("ldi r10, 10") ... } Ist das denn zulässig ? Sprich, kann ich davon ausgehen, daß r10 benutzt werden darf ? Oder muß ich vorher r10 sichern, oder erkennt das mein C-Compiler ? Wie macht man das am besten ? Thorsten
Eigentlich wäre es doch gut wenn der Optimiere den vollen Speicherplatz ausnutzen würde und die Geschwindigkeit optiemiert, damit man einen langsameren Quartz nehmen kann um Strom zu sparen. Dabei sollte der Optimierer aber intelligent vorgehen z.B. die selten genutzten Routienen Speicherplatzoptimieren und die oft benötigten geschwindigkeitsoptimieren. Aber er soll genau analysieren, d.h. wenn in der Hochsprache ein float definiert wurde, der aber nur die Werte 1 und 2 annimmt und diese Variable aber auch noch mit einer anderen multipliziert wird, so wird stattdessen ein bit verwendet und zum multiplizieren der rlf-Befehl genutzt.
Ich hatte auch irgendwo mal Werbung für einen 8051-Optimierer gesehen mit märchenhaften Kompressionsraten und Geschwindigkeitszuwächsen. Ist warscheinlich sowas wie die RAM-Doubler: Man will das Geld von Leuten abgreifen, die sich nicht so auskennen. Und dann verschwindet diese Firma sang und klanglos schnell wieder. Die beste Optimierung kann nur der Programmierer und der Compiler selber machen, da er noch alle Informationen hat. Ist erstmal Assembler draus entstanden und sind alle Adreßbezüge aufgelöst, ist alles vorbei. Zu erkennen, wie man nach Rausstreichen oder Umstellen einer Codesequenz alle Adreßbezüge korrigieren muß, kann kein noch so intelligentes Programm der Welt schaffen. Peter
Ich meine das so: Es ist doch egal wie ein Programm geschrieben ist ASM, C, Basic. Es kommt theoretisch nur auf die Funktion an und diese soll der Nachoptimierer herausfinden und ein Programm generieren, dass effizienter arbeitet. Und wenn das Programm in C geschrieben und Compiliert wurde hat es doch die gleich Funktion nur der genaue Ablauf ist anders. Der Nachoptimierer soll das Programm nicht umschachteln, sondern im ersten Schritt herausfinden wie das Programm reagiert und anschließend weg von diesem Programm einen völlig anderen (optimalen) Code erstellen.
Sagen wir es mal so: Ich habe mir grad was ausgerechnet, es kommt 23 heraus. Kannst du bitte meine Rechnung optimieren?
23 ist hier ja schon das Optimum. Wenn aber der ASM-Programmierer oder Compiler den µC stattdessen immer deine berechnung macht z.B. x = x + 20 x = x + 3 anstelle von: x = x + 23 ist das schon mist. oder wenn man in der Hochsprache schreibt: konst = 23 schleife x = x + konst Befehle... goto schleife und die Variable konst wird nur einmal gesetz und nie verändert, so das man auch schreiben könnte: x = x + 23 anstelle von: x = x + konst so müsste der µC für x = x + konst mehr rechnen als für x = x + 23 weil konst ja erst beim PIC ins W-Register geladen werden musst. Und genau solche Unsinnigkeiten (die ja auch ein Mensch lösen könnte obwohl dieser selbst das Programm nicht erfunden hat) soll der Nachoptimierer finden.
Hi der SDCC ermöglicht tatsächlich soetwas. Die nennen das peep hole optimizer. Hier wird nach der Kompilation des C-Quelltextes der ASM-Coder (vor dem eigentlichen Assemblieren) nochmal geparst und irrige Konstruktionen wie mov R1,#40 orl R1,#30 zu einer Instruktion zusammengefasst. Das ganze ist regelbasiert und kann beliebig erweitert werden. Matthias
Hallo Beisammen ich meine daß man bei einem Hochsprachenprogramm unterscheiden muß in die reinen Hochsprachenbefehle wie if, while, for und die Benutzung der Bibliotheken. Bei ersteren kann der Compiler optimieren, bei der Verwendung der Bibliothek nicht. Natürlich könnte der Compiler optimieren wenn da steht x = x + 20 x = x + 3 aber ich denke daß der Compiler-Hersteller (ganz oben) mit nicht optimal meint, daß die Verwendung der Bibliothek unvermeidlich einen Funktions-Overhead mit sich bringt, den der Compiler gar nicht beeinflussen kann. Ich meine z.B. wenn ich rechen a = 5 + 7, so wird hier die gleiche Funktion verwendet, als wen ich rechne a = 2300 + 4500. Ersteres könnte man mit einem einzigen Assemblerbefehl erschlagen, das 2. Beispiel kann ein 8-Bitter nicht mehr mit einem Befehl erschlagen und hier ist die Bibliothek auch für ausgelegt, also für Integer, LONG Integer oder was noch schlimmer ist: float oder double. Das ist nur ein Beispiel, das trifft für andere Bibliotheksfunktionen - nicht nur für mathematische - zu. Gerhard
Das bringt doch alles nix. Wenn jemand z.B. für den gcc Verbesserungsmöglichkeiten sieht, dann soll er das doch den Entwicklern mitteilen. Dann haben alle was davon. Mir sind noch keine offensichtliche Dummheiten (mit eingeschalteter Optimierung) aufgefallen, aber ich hab auch keine Übung im Assembler.
Hallo Fritz ich habe schon einige Steuerungen mit uC gebaut (PIC), ich verwende dabei immer Assembler. Mein Arbeitskollege hat sich vor kurzem mit nem ST62 und C rumgeärgert. Soll heissen er mußte eine Änderung an einem bestehenden Programm durchführen, aber nach der Änderung hat das Timing einiger Funktionen nicht mehr gepasst. Da genau ist der eigentliche Vorteil des Assemblers. Gerade wenn sich ein Compiler "anmaßt" zu optimieren kann bei Steuerungen Mist rauskommen. Das ist was mir zum Thema Optimieren einfällt. Für mich gilt: Wenns nur um Bit-Klemptnerei geht nimm ich nur Assembler - da weiß ich genaus wann was passiert. Nur wenn's Rechen-intensiev wird, kommt für mich ein C-Compiler in Frage. Gerhard
Wie schon erwähnt: Märchenstunde... Und ich behaupte sowas nicht ienfach so, sondern ich bin auch in der Lage das zu beweisen *g*: int main(void) { int a = 23; int b = 0; int c = 0; return (c = a + b); } Wird von avr-gcc übersetzt mit (aus dem Listfile): ldi r24,lo8(23) ldi r25,hi8(23) Gute Compiler können das also ;)
Nein total schlecht machen die Compiler das nicht, aber es könnte besser gehen. Genau so wie man ein Gleichung auflösen (vereinfachen) kann, so müsste doch das auc mit dem Programmcode gehen z.B. wenn man ein float verwendet anstelle des eigentlich auch geeigneten Bytes oder wenn ein aufwendige Divisionsroutine in den Programmspeicher geschrieben und dann ausgeführt wird auch wenn nur die ein Division x=x/2 im Programm steht wofür nur ein rrf-Befehl nötig ist.
Hallo oldbug das ist eben kein guter Compiler. Aber sowas erfordert auch Intelligenz und das fehlt Computern und Software eben. Es gibt aber und dies bereits schon länger, oprimierende Compiler. Borland C++ - Fans läßt die Optimierfreudigkeit dieses Compilers oft die Haare zu Berge stehen. So hat "optimiert" dieser Compiler: for( i = 0; i < 10000; i++ ); zu nix. Der erkennt, daß da keine Funktion in der for-Schleife steht, schmeißt sie raus und futsch ist die "schöne" Verzögerung. Aber es gibt auch so Superteile wie für den Intel-Risc-Prozessor I860. da optimiert der Compiler sogar die Registerverwendung. Gerhard
Nana, deklarier i volatile und die Schleife bleibt :-) Unsinnige (und das ist diese Schleife für den Compiler nun mal, da sie nichts macht, ausser Zeit zu verschwenden) Schleifen werden wegoptimiert.
btw: würd mich wundern, wenn der avr-gcc die Registerverwendung nicht optimieren würde...
Kann mir mal jemand einen vollständigen C-Code aufschreiben, der optimiert werden soll? Bei meinen Kurz-Testprogramm optimiert er immer alles weg, bzw. rechnet es schon zur compilierzeit aus :-(
@AlterKäfer: Ich meinte einen Code, wo man mehr sieht. Bei mir macht er z.B. aus int test(int x) { return (x/2); } int main(void) { int a = 23; int b = 8; int c,i; c=test(b); for (i=0;i<a;i++) c=c+b+i; a=a+b; a=a/2; return (a); } diesen Code (sogar der Funktionsaufruf wird wegoptimiert): 1:x.c **** int test(int x) 2:x.c **** { 42 .LM1: 43 /* prologue: frame size=0 */ 44 /* prologue end (size=0) */ 3:x.c **** return (x/2); 46 .LM2: 47 0000 97FD sbrc r25,7 49 .LM3: 50 0002 0196 adiw r24,1 51 .L2: 4:x.c **** } 53 .LM4: 54 0004 9595 asr r25 55 0006 8795 ror r24 56 /* epilogue: frame size=0 */ 57 0008 0895 ret 58 /* epilogue end (size=1) */ 59 /* function test size 6 (5) */ 61 .Lscope0: 64 .global main 66 main: 5:x.c **** 6:x.c **** int 7:x.c **** main(void) 8:x.c **** { 68 .LM5: 69 /* prologue: frame size=0 */ 70 000a C0E0 ldi r28,lo8(__stack - 0) 71 000c D0E0 ldi r29,hi8(__stack - 0) 72 000e DEBF out _SP_H_,r29 73 0010 CDBF out _SP_L_,r28 74 /* prologue end (size=4) */ 9:x.c **** int a = 23; 10:x.c **** int b = 8; 11:x.c **** int c,i; 12:x.c **** 13:x.c **** c=test(b); 14:x.c **** 15:x.c **** for (i=0;i<a;i++) 76 .LM6: 77 0012 80E0 ldi r24,lo8(0) 78 0014 90E0 ldi r25,hi8(0) 79 .L8: 81 .LM7: 82 0016 0196 adiw r24,1 83 0018 8731 cpi r24,23 84 001a 9105 cpc r25,__zero_reg__ 85 001c E4F3 brlt .L8 16:x.c **** c=c+b+i; 17:x.c **** 18:x.c **** a=a+b; 19:x.c **** a=a/2; 20:x.c **** 21:x.c **** return (a); 22:x.c **** 23:x.c **** } 87 .LM8: 88 001e 8FE0 ldi r24,lo8(15) 89 0020 90E0 ldi r25,hi8(15) 90 /* epilogue: frame size=0 */ 91 0022 00C0 rjmp exit 92 /* epilogue end (size=1) */ 93 /* function main size 13 (8) */
gibt es auch compiler, die die Verwendung von Interrupts, Timer und andere Peripherie verändern? Und Unterprogramme völlig auseinander reißen und nicht in Unterprogrammen stehende Teile in Unterprogramme schreiben und entscheiden ob etwas im µC berechnet wird oder in der Tabelle nachgeschaut wird?
Eine Übersicht, was der gcc3.4 optimiert findet man auf: http://gcc.gnu.org/onlinedocs/gcc-3.4.0/gcc/Optimize-Options.html#Optimize%20Options
@Gerhard: > Hallo oldbug > > das ist eben kein guter Compiler Warum denn nicht? Es wurde doch alles auf minimale Codegröße reduziert. Und dass der Compiler eine sinnlose Schleife wegoptimiert ist doch nur verständlich. Optimierung auf Maschinencode-Ebene macht der GCC, nennt sich Peephole Optimizer. @Stefan Helmert: > gibt es auch compiler, die die Verwendung von Interrupts, Timer und > andere Peripherie verändern? Mit Sicherheit nicht, ich bezweifle dass ein Programm hier bessere Lösungen finden könnte als ein Mensch.
Nun, und ich würde behaupten das es technisch möglich ist Compiler-Maschinen zu bauen die immer besseren Code erzeugen als es der Mensch je könnte. Es gibt dazu schon einige Ansätze die zB. mit Hilfe von genetischen Algorithmen mathematische Formeln optimieren oder sogar den Programmcode für hocheffiziente Formeln ermitteln. Deren Resultate könnte ein Mensch in der Geschwindigkeit nicht erreichen. Die erzielten Resultate finden meistens auch ein Optimum in einen enorm großen Suchraum. Angenommen man hat einen Assemblercode mit 126 Bytes Code so könnte eine sehr sehr schlechte Maschine alle möglichen Kombinationen von gültigen Code durchprobieren. So ähnlich kann man sich die genetischen Algortihmen vorstellen, nur eben das sie den maximalen Suchraum enorm effizient und schnell durch Selektion begrenzen und durchsuchen können. Ein gleichgelagertes Problem ist das Schachspiel. Auch hier wurde lange Zeit behauptet das ein Computer niemals ein Großmeister schlagen kann. Nun heutzutage behauptet man schon das ein Großmeister die Schachprogramme in naher Zukunft nicht mehr schlagen kann. Auch beim Schach geht es darum aus einem rießigen Suchraum den Besten Zug zu finden. Übertragen auf einen Optimierer hiese das das man aus einem Suchraum von gültigen Maschinencode den Code finden soll der am effizientesten ist. Es stellt sich nun nur noch die Frage ob es schon Forschungen in dieser Richtung gibt, ob ein solches Verfahren effizienter als der Mensch ist und ob man bei der heutigen "Resourceverschwendung" überhaupt so ein Verfahren benötigt. Durchschnittlich gesehen übertreffen heutige Compiler schon jeden Mesnchen. Sie sind umgerechnet auf den Zeit-/Kosten-/Wissensaufwand heute schon effizienter. Gruß Hagen
Ich habe ja schon immer gesagt, dass nur ein Zufallsgenerator der den Hauptspeicher mit zufälligen Bytes füllt reicht um alle möglichen Programme zu schreiben, sogar total bug-frei. Das Problem ist nur, die nicht-funktionierenden Programme auszuselektieren :-)
Ich muss Hagen insofern zustimmen, daß es wohl möglich ist, die Optimierer noch ganz wesentlich zu verbessern! Allerdings wird sich wohl niemand daran aufhalten, einen "Nachoptimierer" zu programmieren. Der effektivste weg wird immer noch der vom Sourcecode bis zum Binary sein!
Hi @Fritz Nicht nur das aussortieren ist das Problem. Wenn wir mal von 8 KByte Speicher ausgehen (also eine angenehme Speichergröße die man zur Not noch mit ASM füllen könnte) macht das 64KBit. Wir haben also 65536 Bits die entweder '0' oder '1' sein können. Also haben wir 2^65536 mögliche Kombinationen. Diese Zahl hat 19729 Dezimalstellen. Das würde ich als Problem bezeichenen :-) Matthias
@Matthias: korrekt, aber so unwahrscheinlich es klingen mag, die Natur, sprich Evolution hat 22 Chromosomen mit Milliarden von Genen zu optimieren und hat es in 1 Millionen Jahre geschafft günstige Kombinationen zu finden die den Menschen ausmachen. Exakt das "Herausfilteren" der potentesten = optimalen Kombinationen aus einem schier unvorstellbar großen Suchraum = max. Kombinationen ist die Stärke von genetischen Algorithmen und Evolutionsstrategieen. Sie werden dann EIN mögliches Optimum als Lösung finden, diese Optimum muß aber nicht zwangsläufig DAS Maximum darstellen. Viele Info's findet man dafür beim sogenannten Problem des Handlungsreisenden "Tavelsman/Salesman Problem". Die genetischen Algos. zur Formelerzeugung mit denen ich experimentiert habe enthielten in ihrem Genaufbau = Allelen die Regelwerke welche Formeloperaoren, Konstanten und Variablen wie korrekt zusammenzubauen sind. Dies ist 1 zu 1 übertragbar auf die Assembler-Befehle. Somit würde man über das clevere Design der Gene die Kombinatonsvielfalt von untauglichen Assemblerkombinationen von vornherein ausschließen. Das einzigste was der Programmier bei solchen Verfahren eingeben muß ist die Selektions-Funktion. Diese entscheidet zu welchem Progranm sich die Zufallserzeugten Individuen entwickeln werden. Aber exakt die klare Definition einer solchen Selektions-Funktion ist das schwierige Problem. Gruß Hagen
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.