Makro verhält sich fehlerhaft bei GNU Compiler Linux u. Windows
-
Ich benutze in meinen Programmen Inline-Funktionen, die auch noch schneller als Makros sind. Ich arbeite nur mit GCC auf Windows und Linux. Aber der Borland Compiler kann angeblich keine Inline-Funktionen im ANSI Standard.
Hmm, ich glaube nicht das Makro's per se langsamer sind als Inline Funktionen. Bei Makros ersetzt der Präprozessor den Aufruf durch den Code während bei Inline Funktion der Linker den Aufruf ersetzt sofern das Kosten zu Nutzen Verhältniss stimmt (VC Compiler)
Aber, ist deine Anwendung so zeitkritisch das du auf ein paar Takte achten musst ?
Ich habe nämlich das Disassembly eines Testprojekts angeschaut und dort festgestellt das der Optimierer (alter VC Compiler) manchmal die Funktionen automatisch inlined ohne das ich explizite inline Funktionen hätte. Und seither stehe ich ein wenig kritisch gegenüber wenn es um Einsparungen von einigen wenigen Takten geht. Was nützt es dir wenn du hier und da ein paar Takte sparen willst wenn dein Optimierer das eh macht ? Alles unter der Vorraussetzung das du keine Sünden im Code hast.
Kann viel gelabert werden, um Makros kommt man aber oft nicht herum.
So zeitkritisch ???
Makro's funktionieren aber nur wenn man auf mögliche Seiteneffekte verzichtet. Funktionen sind da schöner, sie funktionieren auch mit Seiteneffekten. Sind also universeller. Und die schlechte Debuggingmöglichkeit ist meines Erachtens eh ein KO Kriterium.
-
Tim schrieb:
Zweitens ist inline keine Garantie dass auch geinlined wird.
Dann hat das aber auch einen guten Grund. Zum Beispiel, dass es ohne inline schneller ist. Der Compiler kann das beurteilen. Beim Makro ist er zum inline gezwungen und der Programmierer muss wissen, ob dies gerechtfertigt ist oder nicht.
-
kjesse schrieb:
Es kommt keine Warning, aber der gleiche Fehler beim Ausführen.
Was für ein Fehler? Du hast bisher nur geschrieben, dass das Verhalten anders als beim Sun oder Borland ist, und dass da irgendwas zweimal ausgeführt werden würde, ohne genauer zu beschreiben, was du eigentlich beobachtest.
Dazu möchte ich noch anmerken, dass in der Version die Casts fehlen. Sofern die im Ausgangscode notwendig (sprich: nicht nur Voodoo-Angstcode) waren, sind sie höchstwahrscheinlich auch jetzt noch notwendig. Im Zweifel poste die Definition des Strukturtyps von lpnadc.
-
Bitte ein Bit schrieb:
Wie heißt es so schön in Effective C++: schon nur an Makro's zu denken ist schmerzhaft.
(...)
Makro's haben hübsche Seiteneffekte, da es bei Makro um ein dummen Ersetzungsvorgang handelt, und sind ebenfalls auch noch schwer zu debuggen. Sie sind daher nicht empfehlenswert.
Makros sind subba!
Makros sind aber auch wie ein Hammer. Wenn man einen Nagel hat, ist ein Hammer subba! Und wenn man mit dem Hammer Schrauben in die Wand hämmert, dann ist deswegen nicht der Hammer schlecht.
-
Also Schrauben mit dem Hammer "schrauben" geht wunderbar und hält genau so gut wie geschraubt. :p
Anyway, Makros sind genial, nur als Funktionen missbraucht Mist.
-
Bitte ein Bit schrieb:
So zeitkritisch ???
Irgendwas ist immer am oberen Rand. Laufzeit, RAM, ROM. Das wechselt ständig. Die Frage ist ja, was die Funktionen machen deren Aufrufkosten man sparen will. Steckt dahinter richtig was, dann stört es kaum, steckt dahinter vielleicht nur ein Opcode, dann will ich dafür sicher keine Funktion aufgerufen haben.
SeppJ schrieb:
Tim schrieb:
Zweitens ist inline keine Garantie dass auch geinlined wird.
Dann hat das aber auch einen guten Grund. Zum Beispiel, dass es ohne inline schneller ist.
Ich kann mir gerade nicht so recht einen Fall konstruieren wo es schneller wäre eine Funktion nicht zu inlinen. Imho ist das eher ein Kompromiss aus Laufzeit und Codegröße. Und evtl. auch Stack.
-
Tim schrieb:
Ich kann mir gerade nicht so recht einen Fall konstruieren wo es schneller wäre eine Funktion nicht zu inlinen. Imho ist das eher ein Kompromiss aus Laufzeit und Codegröße. Und evtl. auch Stack.
Zu hohe Codegröße sprengt dir den Cache und geht dann auf die Performance.
-
Na da bin ich froh keinen Cache zu haben
-
Ich hatte im Dezember einen Kompressor geschrieben und dabei die Hashfunktion und den selbst geschriebenen memcmp zum byteweisen Vergleich durch "static inline" Funktionen ersetzt und mit einem 1 GByte File getestet. Inline war beim Komprieren schneller als Makro oder Funktionsaufruf, aber der Effekt war nicht riesig. Bei kleinen Dateien fällt das vermutlich nicht ins Gewicht.
-
Makros sind subba!
Makros sind subba und wenn diese auch noch optimal gelingen sind diese auch suboptimal...
Zu hohe Codegröße sprengt dir den Cache und geht dann auf die Performance.
Ist das jetzt sarkastisch gemeint ?Ich kann mir gerade nicht so recht einen Fall konstruieren wo es schneller wäre eine Funktion nicht zu inlinen. Imho ist das eher ein Kompromiss aus Laufzeit und Codegröße. Und evtl. auch Stack.
Im Fall wo es auf jedes (Kilo)Byte, jeden Takt ankommt, verstehe ich deine Argumente.
Aber auf etwas größeren Prozessoren und einem etwas guten Compiler würde ich von solchen Mikrooptmierungen eher abraten. Auf der einen Seite sind Makro's vielleicht etwas schneller, verbrauchen weniger Speicher (paar Bytes) und benötigen ein paar Takte weniger, sind aber dafür fehleranfälliger und kaum debuggbar. Funktionen haben die Makro-typsichen Fehler nicht, sind debuggbar, benötigen dafür aber ein wenig mehr Speicher und Takte.
Ich könnte auch genausogut argumentieren dass das Überprüfen der Speichergrenzen von Arrays ineffizient ist. Verbraucht auch ein paar Takte mehr und benötigt auch mehr Code.
Wer garantiert eigentlich das der Compiler/Optimierer nicht bereits solche Optimierungen ohne dein zutun macht? Der VC Compiler/Optimierer ist da böse, er fummelt auf höchster Optmierunsstufe schon erheblich am Code herum, behandelt Funktionen als inline, zerlegt for-Schleifen, ...
-
Bitte ein Bit schrieb:
Zu hohe Codegröße sprengt dir den Cache und geht dann auf die Performance.
Ist das jetzt sarkastisch gemeint ?Nein. Was lässt dich das vermuten?
-
Tim schrieb:
Zum einen unterstützen weder Borland noch MSVC die neueren C-Standards (C99 aufwärts) und sollten demnach im C-Modus auch kein inline verstehen. Zweitens ist inline keine Garantie dass auch geinlined wird. Ergo: Kann viel gelabert werden, um Makros kommt man aber oft nicht herum.
Macros sind der Spezialfall. Allgemein sollte man inline bevorzugen. Das heißt natürlich nicht, dass man niemals nie Macros verwenden darf. Aber allgemein sollte Macros vermeiden.
Ein guter Einsatzzweck ist zB die ganzen "forced inline" Varianten der verschiedenen Compiler portabel zu benutzen
#ifdef __GNUC__ #define FORCE_INLINE __attribute__((always_inline)); #elif ANDERERCOMPILER #define FORCE_INLINE foobarinline #else #error "no force inline" #endif
-
Nein. Was lässt dich das vermuten?
Der Sinn deines Satzes bezogen auf einen Otto-Normal-Entwicklungsrechner mit modernen Prozessor: Zu hohe Codegröße sprengt dir den Cache und geht dann auf die Performance.
Das würde ja implizieren das eine hohe Codegröße mit einem Performanceverlust einhergeht, was so nicht stimmt. Wenn ein Prozessor 4 kByte L1-Cache hat, bedeutet dann dass alle Programme > 4 kByte langsam sind ?
Was ist mit der Cache-Prediction ?
-
Bitte ein Bit schrieb:
Der Sinn deines Satzes bezogen auf einen Otto-Normal-Entwicklungsrechner mit modernen Prozessor: Zu hohe Codegröße sprengt dir den Cache und geht dann auf die Performance.
Das ist sogar mein Wortlaut.
Das würde ja implizieren das eine hohe Codegröße mit einem Performanceverlust einhergeht, was so nicht stimmt. Wenn ein Prozessor 4 kByte L1-Cache hat, bedeutet dann dass alle Programme > 4 kByte langsam sind ?
Die Programmgröße ist uninteressant, aber es gibt schlagartig Einbrüche, wenn der Code einer performancekritischen Schleife mehr als 4 kByte groß ist.
Was ist mit der Cache-Prediction ?
Keine Ahnung, erzähl du's mir.
Ich frage mich nach wie vor, wieso du von Sarkasmus ausgehst. Kann doch sein, dass ich einfach uninformiert bin. Wenn du es besser weißt, lass hören!
-
Performanceverlust durch massives Inlining ist ein realer Effekt, auch auf modernen Rechnern. Und zwar durchaus recht heftig
. Du kannst ja gerne mal ein paar Tests machen. Das Problem ist nämlich, das viel Code mehrfach ausgeführt wird. Und wenn dieser Code total aufgeblasen ist, weil jede Funktion mehrfach drinsteht anstatt den Code einmal zu haben und ansonsten nur einen Call, dann kann es schnell passieren, dass bei einer Schleife in jedem Durchgang der Code vom Anfang nochmal nachgeladen werden muss, weil das Schleifeninnere nicht mehr als ganzes in den IC passt. Da nützt dir auch keine Prediction etwas und das hat auch überhaupt nichts mit der Gesamtgröße des Programms zu tun.
edit: Boah, Bashar, du ninjast mich heute schon zum zweiten Mal!
-
Performanceverlust durch massives Inlining ist ein realer Effekt...
Das ist mit klar, aber ich habe mich extra auf einen sauberen Code bezogen, wo also inline Funktionen nicht bis zum Erbrechen benutzt wird.
MSDN zu inline
Indiscriminate use of __forceinline can result in larger code with only marginal performance gains or, in some cases, even performance losses (due to increased paging of a larger executable, for example).
@Bashar:
Tut mit leid, aber deine Wort verwirren mich.