C schneller als C++



  • Ein C-Programm lässt sich mit Sicherheit schneller übersetzen als ein C++-Programm.

    Ein perfektes C++-Programm läuft mit ziemlicher Sicherheit schneller als ein C-Programm. Dies gilt insbesondere für C++ 11 (mit seinen Verschiebe-Operationen), aber auch für normales C++.

    Der Grund ist einfach: C++ weiß einfach viel mehr über ein Programm (kann viel mehr Annahmen treffen), als dies ein C-Programm weiß. Dadurch kann ein C++-Compiler viel aggressiver optimieren als ein C-Compiler.

    Das gilt wie geschrieben nur für jeweils "optimale" (perfekt optimierende) Compiler für C und C++.

    Gilt auch für Templates, denn ein Template konstruiert ja automatisch für jeden neuen Typ neuen Sourcecode (ist ja eigentlich nur ein "intelligentes Preprozessor- Makro") - mit einem Template kann man das erzeugte Binär-File nicht verkleinern. Hat man ein Template für int, long, benutzerdefinierten Typ werden auch für jeden dieser Typen eigener Code generiert (also 3 verschiedene Codes für jeden Typ). Templates sind eben keine echten "Generika".



  • PushButton schrieb:

    Ist die Diskussion nicht irgendwie sinnlos, da ja C eine Teilmenge von C++ ist und ich jederzeit einfach so oder in einer Methode reinen C-Code verwenden kann wenn ich dies möchte?

    Das ist nicht ganz richtig. C++ ist zwar so kompatibel mit C wie möglich, aber C ist keine echte Teilmenge von C++. Es gibt C-Programme die sich nicht mit einem C++ Compiler übersetzen lassen, auch wenn das nur sehr spezielle Fälle betrifft. In der Praxis trifft das, was du geschrieben hast auch weitestgehend zu: Ich könnte in C++ wenn ich das möchte so schrieben als wäre es C, habe aber weit mehr Möglichkeiten wenn ich das möchte.

    C++-Konstrukte sind oft sehr viel näher am Problem und bieten modernen Compilern damit deutlich bessere Optimierungsmöglichkeiten. Als die Compiler noch schlechter waren sah es vielleicht anders aus.

    Gerade Templates bieten die Möglichkeit sehr generischen Code zu schreiben, ohne Typinformationen zu verlieren oder sich das mit zusätzlichen Indirektionen zu erkaufen. Daher ist std::sort in der Regel auch schneller als qsort.



  • TNA schrieb:

    Es gibt C-Programme die sich nicht mit einem C++ Compiler übersetzen lassen, auch wenn das nur sehr spezielle Fälle betrifft. In der Praxis trifft das, was du geschrieben hast auch weitestgehend zu: Ich könnte in C++ wenn ich das möchte so schrieben als wäre es C, habe aber weit mehr Möglichkeiten wenn ich das möchte.

    Die grössere Anzahl Möglichkeiten macht es für den C++-Compiler aber auch schwieriger, gleichen Code zu optimieren. In C++ müssen (vom Compiler) allerhand Vorsichtsmassnahmen für mögliche Exceptions getroffen werden, was das Binary aufbläht und u.U. langsamer macht.

    C++ ist fast "you don't pay for what you don't use" aber eben nicht ganz.



  • ant schrieb:

    In C++ müssen (vom Compiler) allerhand Vorsichtsmassnahmen für mögliche Exceptions getroffen werden, was das Binary aufbläht und u.U. langsamer macht.

    C++ ist fast "you don't pay for what you don't use" aber eben nicht ganz.

    Exeptions waren lange Zeit eine der zwei Ausnahme von der Regel "you don't pay for what you don't use". Das gilt aber nicht mehr seit C++11. Wenn man an eine Funktion NOEXEPT dran schreibt, gibt es Null Overhead.



  • ant schrieb:

    In C++ müssen (vom Compiler) allerhand Vorsichtsmassnahmen für mögliche Exceptions getroffen werden, was das Binary aufbläht und u.U. langsamer macht.

    Jein. Das läuft auf modernen Compilern über seperate Maps. dh du zahlst zwar binary size beim Laden der Anwendung aber keine Laufzeit, da der IP genommen wird und Anhand des Wertes IP weiß das Programm was es aufräumen muss.



  • @ant
    Wieso nicht ganz, soweit ich weiß läuft der Compiler nur einmal durch und wenn man keine Ausnahmen oder virtuelle Methoden nutzt, dann muss man auch nicht dafür "bezahlen" wenn das Programm läuft.



  • PushButton schrieb:

    Wieso nicht ganz, soweit ich weiß läuft der Compiler nur einmal durch und wenn man keine Ausnahmen oder virtuelle Methoden nutzt, dann muss man auch nicht dafür "bezahlen" wenn das Programm läuft.

    Es kommt darauf an wie Exceptions implementiert sind, prinzipiell geht es dabei um das Stack Unwinding (aufräumen).

    Hier was zum lesen: https://magazin.c-plusplus.net/artikel/Modernes Exception-Handling Teil 2 - Hinter den Kulissen



  • johan schrieb:

    Ein perfektes C++-Programm läuft mit ziemlicher Sicherheit schneller als ein C-Programm. Dies gilt insbesondere für C++ 11 (mit seinen Verschiebe-Operationen), aber auch für normales C++.

    Ist jetzt sehr subjektiv was man als "perfektes C++ Programm" bezeichnen würde, nicht? Und ein bisschen unfair wenn du vom C Programm nicht ebenso forderst "perfekt" zu sein. Schneller als ein stümperhaftes Programm in Sprache X zu sein ist schliesslich kein wirklich interessantes Kriterium.

    ----

    Es gibt Fälle wo ein "idiomatisches" C++ Programm schneller sein wird als ein "idiomatisches" C Programm.
    Es gibt Fälle wo ein "idiomatisches" C++ Programm langsamer sein wird als ein "idiomatisches" C Programm.

    Und ein perfekt optimiertes C++ Programm wird wohl inetwa genau so schnell sein wie ein perfekt optimiertes C Programm.

    Interessant ist also IMO eher der Vergleich idiomatischer C++ und C Programme. Dummerweise ist auch das, also was ein idiomatisches C++ bzw. C Programm ist, sehr subjektiv.
    Ich sehe aber keinen Grund zu behaupten dass jedes (nichtmal fast jedes) idiomatische C++ Programm schneller sei als ein idiomatisches C Programm.

    Deine Begründung

    johan schrieb:

    C++ weiß einfach viel mehr über ein Programm (kann viel mehr Annahmen treffen), als dies ein C-Programm weiß. Dadurch kann ein C++-Compiler viel aggressiver optimieren als ein C-Compiler.

    kann ich auch nicht nachvollziehen. Kannst du ein Beispiel dafür bringen was du hier meinst? Also welche Optimierungen ein C++ Compiler aufgrund welches Wissens machen könnte, die der C Compiler nicht machen kann?



  • Wie misst man diese "C ist schneller als C++" in der Praxis? Das einzige was ich gefunden habe sind solche Benchmarks hier:http://benchmarksgame.alioth.debian.org/u32/c.php

    Da geben sich die beiden Sprachen nicht viel von der Performance.



  • hustbaer schrieb:

    Also welche Optimierungen ein C++ Compiler aufgrund welches Wissens machen könnte, die der C Compiler nicht machen kann?

    Hier wurde schon ein Beispiel genannt:

    TNA schrieb:

    Gerade Templates bieten die Möglichkeit sehr generischen Code zu schreiben, ohne Typinformationen zu verlieren oder sich das mit zusätzlichen Indirektionen zu erkaufen. Daher ist std::sort in der Regel auch schneller als qsort.

    Ich habe das jetzt nicht selbst überprüft, halte es aber für wahrscheinlich richtig. Der Compiler hat quasi keine Chance die Indirektion über den Funktionspointer bei qsort zu durchschauen und irgendwas zu optimieren oder zu inlinen.


  • Mod

    sebi707 schrieb:

    hustbaer schrieb:

    Also welche Optimierungen ein C++ Compiler aufgrund welches Wissens machen könnte, die der C Compiler nicht machen kann?

    Hier wurde schon ein Beispiel genannt:

    TNA schrieb:

    Gerade Templates bieten die Möglichkeit sehr generischen Code zu schreiben, ohne Typinformationen zu verlieren oder sich das mit zusätzlichen Indirektionen zu erkaufen. Daher ist std::sort in der Regel auch schneller als qsort.

    Ich habe das jetzt nicht selbst überprüft, halte es aber für wahrscheinlich richtig. Der Compiler hat quasi keine Chance die Indirektion über den Funktionspointer bei qsort zu durchschauen und irgendwas zu optimieren oder zu inlinen.

    Das kann man aber alles auch in C machen. Der Code wird bloß übelst viel länger.



  • SeppJ schrieb:

    Das kann man aber alles auch in C machen. Der Code wird bloß übelst viel länger.

    Gut kann man immer machen. Ich hab jetzt eher idiomatisches C mit idiomatischem C++ verglichen.



  • PushButton schrieb:

    Wie misst man diese "C ist schneller als C++" in der Praxis? Das einzige was ich gefunden habe sind solche Benchmarks hier:http://benchmarksgame.alioth.debian.org/u32/c.php

    Benchmarks sind meistens ziemlicher Muell. Sie messen nur bestimmte Teilaspekte einer sprache. Haeufig bestehen Benchmarks aus verschachtelten Schleifen und viele gleichartige Rechenoperationen darauf, z.b. Matrixmultiplikationen. In der Praxis hat man aber zu grossen Teilen die Interaktion vieler verschiedener Objekte.
    Zudem sind die Benchmarks oft bis zum letzten Takt durchoptimiert, bei C auch gerne mal mit plattformabhaengigen intrinsics gespickt, waehrend man normalerweise viel mehr Wert auf uebersichtlichkeit legt.



  • @sebi707
    Gut, die Optimierung kann der C Compiler nur schwer machen. (Dass er sie generell nicht machen kann kann man so nicht sagen, denn auch C Compiler können und dürfen inlinen. Das Problem wird eher sein dass qsort bereits fix & fertig compiliert in der CRT vorliegt, der Compiler daher qsort nicht inlinen wird, und dann natürlich auch den Aufruf der Vergleichsfunktion in qsort nicht inlinen kann.)

    Nur... dann muss diese Optimierung eben der C Programmierer machen.

    Der Vergleich ist nämlich nicht fair - es wird ein Feature das C nicht hat (Templates) mit dem idiomatischen, einfachen Milchmädchenersatz in C verglichen. Nicht mit einem optimalen C Programm.
    Das optimale C Programm könnte z.B. den Präprozessor verwenden um das Sort-Template nachzubilden. Oder eine mit Hand ausgestanzte Sort Implementierung für alle nötigen Typen beinhalten.

    Was idiomatisches C vs idiomatisches C++ angeht hab ich eh schon geschrieben: das wird mal so mal so ausgehen. Mir geht es um die Aussage von johan, die mMn. impliziert dass ein C++ Compiler Dinge optimieren kann, die man in C gar nicht (bzw. nicht mit vertretbarem Aufwand) so schreiben kann dass sie gleich schnell wären.

    ps: Wäre mal interessant zu gucken ob aktuelle C Compiler es schaffen die Vergleichsfunktion bei einer im Source vorliegenden qsort Funktion zu inlinen. Würde mich nämlich fast wundern wenn sie das nicht schaffen.



  • hustbaer schrieb:

    Der Vergleich ist nämlich nicht fair - es wird ein Feature das C nicht hat (Templates) mit dem idiomatischen, einfachen Milchmädchenersatz in C verglichen.

    Naja ich vergleiche die Sortierfunktion der C Standardbibliothek mit der der C++ Standardbibliothek. Ich denke gerade dieser Vergleich ist hoch relevant dafür, wie Programme üblicherweise geschrieben werden. Natürlich ginge es in C wahrscheinlich noch besser, aber das dürfte für die Praxis nicht sonderlich relevant sein.



  • Natürlich ginge es in C wahrscheinlich noch besser, aber das dürfte für die Praxis nicht sonderlich relevant sein.

    nein ging es nicht - bei C++ und Templates ist es so generisch wie die C-stdlib-Lösung, aber so performant wie die C-von-Hand-inlining-Lösung - also gewinnt bei diesem Beispiel immer C++, das kombiniert mit Move-Semantik und saubere Const-Correctness gibt viel Potential - man braucht aber schon ein paar Jahre Erfahrung - in richtigem Benchmarken (und teilweise lesen von Assembler) um das sehen zu können



  • @Gast3
    Dein Beitrag liest sich so, wie von jemandem geschrieben, der gerne und viel zu dem Thema liest, aber wenig selbst ausprobiert hat.
    Nein, ein compileroptimiertes Kompilat eines idiomatischen C++ Programms kann nicht in jedem Fall mit hangeschriebenem C-Code mithalten.

    Manchmal, klar. Oft, vermutlich. Immer, ... Blödsinn.



  • @Gast3
    Dein Beitrag liest sich so, wie von jemandem geschrieben, der gerne und viel zu dem Thema liest, aber wenig selbst ausprobiert hat.

    eher einer der viel selbst ausprobiert und weniger liest - ich bin da schon ganz tief mit den Pfoten drinn

    Nein, ein compileroptimiertes Kompilat eines idiomatischen C++ Programms kann nicht in jedem Fall mit hangeschriebenem C-Code mithalten.
    Manchmal, klar. Oft, vermutlich. Immer, ... Blödsinn.

    Ok das 100% Immer war ein wenig zu streng - man schafft die gleiche/bessere Flexibilität (auch ohne Macros) bei gleicher/besserer Geschwindigkeit

    z.B. wird dein C integer hustbaer_vector vielleicht genauso inlinebar sein wie mein C++
    integer gast3_vector, aber da du keine const-Correctness sauber ausdruecken kannst generiert der Kompiler an manchen deiner Aufrufe mehr Code drumherum - wo er es sich bei mir sparen kann usw. kommt aber auf den Anwendungfall an ob man das überhaupt bemerkt


  • Mod

    const-correctness (oder const im Allgemeinen) hat keine Auswirkungen auf Performance. Ob ein Objekt geändert wird oder nicht, weiß der Compiler schon ganz genau, dazu braucht er kein Versprechen vom Programmierer. Andererseits kann dieses Versprechen mittels viel zu vieler Ausnahmen und Tricks viel zu leicht gebrochen werden, man könnte sich gar nicht da drauf verlassen, selbst wenn man es nötig hätte.

    const ist ein Feature, um dem Programmierer fehlerfreies Entwickeln einfacher zu machen.



  • const-correctness (oder const im Allgemeinen) hat keine Auswirkungen auf Performance.

    ganz klar: sollte es nicht

    ich habe ein Beispiel (kann ich leider nicht herausgeben) wo ein 2D-Daten-Verwaltungscontainer unter VS2010 ca. 5% schneller arbeitet wenn er const-correct ist - aber moeglicherweise wäre er mit dem gcc/clang kompiliert auch ohne const gleich schnell

    also eher nicht "Standard" sondern Kompilerbesonderheiten - also ist mein Beispiel mit const eher unangebracht

    VS2010 loest z.B. globale Referenzen auf globale uint16_t nicht auf, globale const Pointer werden aber aufgelöst


Anmelden zum Antworten