C schneller als C++



  • 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



  • hustbaer schrieb:

    @Gast3
    Nein, ein compileroptimiertes Kompilat eines idiomatischen C++ Programms kann nicht in jedem Fall mit hangeschriebenem C-Code mithalten.

    Das kommt sicherlich stark darauf an, wer den C-Code schreibt. Wenn das ein super C-Experte ist, der sich noch dazu mit der Zielarchitektur bestens auskennt, kann der in manchen fällen vermutlich durch handoptimierten C-Code noch etwas herausholen was der C++ Compiler nicht schafft. Das ist aber weit weg von jeder täglichen Praxis und zum Thema Lesbarkeit und Wartbarkeit ist da auch noch nichts gesagt. Ich denke das es für jemanden der C++ einigermaßen beherrscht einfacher ist in seiner täglichen Arbeit performanten Code zu schreiben als in C.



  • @TNA
    Es kommt nicht nur drauf an wer den C-Code schreibt. Es kommt auch drauf an wer den C++ Code schreibt. Und um was für Code es sich handelt.

    @Gast3
    Würdest du iostreams als idiomatisches C++ bezeichnen? Willst du behaupten dass iostream Code, so wie ihn ein normaler C++ Programmierer schreiben würde (also ohne z.B. spezielle eigene Streambuffer-Klassen, ohne direkte Verwendung des Streambuffers -- einfach nur mit Streams), mit auch nur halbwegs schlau geschriebenem C Code mithalten kann? Wenn ja, dann probier es bitte aus. Ich hab' schon länger keinen Vergleich mehr gemacht, kann sein dass sie die Sache ein wenig verbessert hat. Alle Vergleiche die ich allerdings gemacht habe waren vernichtend. Für C++.

    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

    Wieso kann man in C "keine const-Correctness sauber ausdruecken"? Und wieso sollte der Compiler nicht das ganze Programm mit LTO/LTCG bauen -- womit er dann eigentlich überall weiss was sich wo ändert und was nicht. (Bis auf Stellen wo externe Funktionen wie z.B. OS Funktionen aufgerufen werden -- wo der C++ Compiler aber auch nix machen kann.)

    Man kann in C++ wirklich schön schnelle Programme schreiben, ja. Und das einigermassen angenehm und flexibel. Speziell wenn man zur Not auch mal das Rad neu erfindet. Sobald man aber anfängt praktischerweise die Standardlibrary zu verwenden, überall dort wo man sich damit Arbeit sparen kann, fängt das Programm an langsamer zu werden. Auf Python Niveau wird man es nie schaffen, aber von "optimal" ist man ganz schnell ein gutes Stück weit weg.



  • SeppJ schrieb:

    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.

    Das ist so im Allgemeinen nicht korrekt.

    extern void f(int const &);
    
    int const i = irgendwas();
    f(i);
    //Compiler weiß: i hat sich durch den Aufruf nicht geändert
    
    int j = irgendwas();
    f(j);
    //j könnte sich geändert haben, weil man const bei Referenzen wegcasten darf
    

    const liefert hier eine Zusatzinformation, mal wieder durch undefiniertes Verhalten (Ändern einer const Variablen). Der Compiler kann dadurch womöglich ein load vermeiden.



  • Würdest du iostreams als idiomatisches C++ bezeichnen?

    nein eher als Versuch wie man IO generisch abbilden könnte - ist ganz doll in die Hose gegangen - für Standardfälle (sau) langsam und nicht wirklich einfach anpassbar

    Und warum warum? Blockoperationen und das mögliche Optimierungspotential wurden einfach ignoriert

    stream << X << Y << Z ist eben keine solche - und auch nicht als solche durch Templates oder sonstige Tricks "wahrnehmbar"

    ein triviales fprintf(fp,"%i %i %i", X, Y, Z) ist da schon besser optimierbar



  • Also wenn ich IO in C++ Programmen sehe, dann sehe ich oft: entweder MFC, Qt, sonstiges grausames Framework, oder eben iostreams. Eigenen Code sehe ich da kaum. Und nicht-grausame Libraries kenne ich auch keine.

    Ich würde iostreams also schon als idiomatisches C++ bezeichnen. Auch weil es so unterrichtet wird, in vielen Tutorials zu sehen ist, in vielen Antworten auf Seiten ala Stackoverflow verwendet wird, hier im Forum dauernd in Beispielen verwendet wird etc. Ist halt einfach Standard 😉

    Und da wir uns einig sind darüber dass man mit iostreams Programme ganz schnell ganz langsam machen kann, bin ich eben auch nicht mit der Behauptung einverstanden dass idiomatische C++ Programme unbedingt irgendwie schnell wären.



  • Und da wir uns einig sind darüber dass man mit iostreams Programme ganz schnell ganz langsam machen kann, bin ich eben auch nicht mit der Behauptung einverstanden dass idiomatische C++ Programme unbedingt irgendwie schnell wären.

    Wenn du die "normalen" Entwickler meinst geben ich dir recht - da kann man viel falsch machen, aber ich kann auch ohne Standardbibliothek idomatisch C++ - das meinte ich


  • Mod

    TyRoXx schrieb:

    const liefert hier eine Zusatzinformation, mal wieder durch undefiniertes Verhalten (Ändern einer const Variablen). Der Compiler kann dadurch womöglich ein load vermeiden.

    Wenn da eine Funktion kommt, deren Code der Compiler nicht kennt, wie soll er sich da ein load sparen können? Soll er die Funktion nett darum bitten, keine Register zu benutzen?


Anmelden zum Antworten