The "C is Efficient" Language Fallacy



  • maximAL schrieb:

    +fricky schrieb:

    das sagst du so. allein schon der compiler könnte z.b. die methode inlinen, dabei feststellen, dass lhs und rhs gleich sind

    Das kann meistens eben nicht zur Kompilierzeit festgestellt werden.

    +fricky schrieb:

    (bei dem tippfehler-beispiel)

    ...ich geb dir gleich Tippfehler...

    Du weißt doch es genügt, wenn der Kompiler Code erzeugt der in 99% der Fälle korrekt ist.



  • maximAL schrieb:

    +fricky schrieb:

    das sagst du so. allein schon der compiler könnte z.b. die methode inlinen, dabei feststellen, dass lhs und rhs gleich sind

    Das kann meistens eben nicht zur Kompilierzeit festgestellt werden.

    das ist sehr einfach festzustellen. du übergibst nämlich zwei mal das gleiche objekt. selbst meine Java-IDE (intellij-idea) hat bei deinem beispiel gemeckert, dass hier was nicht stimmen kann.
    🙂



  • void foo(int* lhs, int* rhs, int* val)
    {
      *lhs += *val;
      *rhs += *val;
    }
    

    OMG, mein Compiler kann diese Zeilen nicht optimieren. Parallelisierung ist nie einfach und die eigentliche Performance holt man nicht aus der Microoptimierung.

    adaptive optimization may take advantage

    Irgendwie stoert mich der Konjunktiv. Was ist denn nun wirklich?



  • knivil schrieb:

    void foo(int* lhs, int* rhs, int* val)
    {
      *lhs += *val;
      *rhs += *val;
    }
    

    OMG, mein Compiler kann diese Zeilen nicht optimieren.

    schreib mal 'restrict' vor die pointer (dein compiler muss aber C99 kennen, z.b. GCC). vielleicht tut er's ja dann.
    🙂



  • knivil schrieb:

    void foo(int* lhs, int* rhs, int* val)
    {
      *lhs += *val;
      *rhs += *val;
    }
    

    OMG, mein Compiler kann diese Zeilen nicht optimieren. Parallelisierung ist nie einfach und die eigentliche Performance holt man nicht aus der Microoptimierung.

    Das Problem ist, dass der Compiler quasi nichts parallelisieren kann. Das ist ein relevantes Problem.



  • schreib mal 'restrict' vor die pointer (dein compiler muss aber C99 kennen, z.b. GCC). vielleicht tut er's ja dann.

    bist du Reporter? 🤡



  • Das Problem ist, dass der Compiler quasi nichts parallelisieren kann. Das ist ein relevantes Problem.

    Nur zur Klarstellung: Was, wie und in welchem Massstab bedeutet hier parallelisieren? UV-Pipeline, Mehrkern, ... ?

    C ist halt nah an der Maschine. Entweder abstrahiert man von der Maschine oder spezialisiert man fuer eine Maschine. C oder auch C++ tut beides nicht. Das ist kein Nachteil. Warum soll C++ alles koennen? Wenn man so etwas haben moechte, dann parallelisiert man selbst oder man nimmt sich z.B. eine funktionale Sprache und laesst sich parallelen Code generieren. In beiden Faellen muss man Gehirnschmalz investieren, zum einen parallelisiert man selbst oder muss halt die neue Sprache lernen. Und wenn jemand behaupt, dass z.B. Java schneller sein soll als C++, dann hat er vielleicht hier und da etwas weniger Gehirnschmalz investiert. Und dann auf die super tolle Jit-Blub verweisen, ich weiss nicht ...

    Ich koennte ja noch 'ne Geschichte zum Besten geben mit Agent Nero in Mission Iso-Image brennen. Installer: 500 MByte ... die modernen Alleskoenner. Ich will sie nicht.



  • knivil schrieb:

    Nur zur Klarstellung: Was, wie und in welchem Massstab bedeutet hier parallelisieren? UV-Pipeline, Mehrkern, ... ?

    Jede Art von Parallelisierung.

    Das Problem ist nämlich, dass jedes Statement dass Pointer liest oder schreibt jedes andere Statement verändern kann. Egal welche Art der Parallelisierung - sogar in der Pipeline selber drinnen, ist mit Zeigern enorm problematisch.

    C ist halt nah an der Maschine. Entweder abstrahiert man von der Maschine oder spezialisiert man fuer eine Maschine. C oder auch C++ tut beides nicht. Das ist kein Nachteil. Warum soll C++ alles koennen? Wenn man so etwas haben moechte, dann parallelisiert man selbst oder man nimmt sich z.B. eine funktionale Sprache und laesst sich parallelen Code generieren.

    Es ist ein relevantes Problem dass C/C++ Code einfach in gewissen Situationen lahm ist. Da kannst du auch kein Gehirnschmalz oder sonstwas investieren - dieser Aspekt an C++ suckt einfach. Deshalb ist dringend restrict in C++ notwendig...

    Und wenn jemand behaupt, dass z.B. Java schneller sein soll als C++, dann hat er vielleicht hier und da etwas weniger Gehirnschmalz investiert. Und dann auf die super tolle Jit-Blub verweisen, ich weiss nicht ...

    Es ist aber so. In gewissen Situationen wird Java immer schneller sein als C++.



  • ist mit Zeigern enorm problematisch

    Vielleicht hilft es, Zeiger vorsichtig einzusetzen.

    In gewissen Situationen wird Java immer schneller sein als C++.

    Glauben ist gut, Kontrolle ist besser. Da ich wenig mit Java arbeite, kann ich nicht viel darueber sagen. Aber ich bin offen und schaue mir auch gern Beispiele an (sofern sie nicht allzu gross sind).



  • knivil schrieb:

    Glauben ist gut, Kontrolle ist besser. Da ich wenig mit Java arbeite, kann ich nicht viel darueber sagen. Aber ich bin offen und schaue mir auch gern Beispiele an (sofern sie nicht allzu gross sind).

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    PS:
    Zeiger vorsichtig einsetzen ist nicht. denn fast alles in C++ kommt irgendwie auf zeiger zurück. strings, arrays, jede datenstruktur. und das ist eben das problem.



  • Shade Of Mine schrieb:

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    doch, memcpy() nehmen.
    🙂



  • +fricky schrieb:

    Shade Of Mine schrieb:

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    doch, memcpy() nehmen.
    🙂

    👍

    Oder gleich std::copy<T>, welches sich auch noch spezialisieren lässt, und z.B. für bestimmte Datentypen einen speziellen Copy-Algo nutzen könnte (z.B. einen Blitter 😃 ).



  • +fricky schrieb:

    Shade Of Mine schrieb:

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    doch, memcpy() nehmen.
    🙂

    Und wenn der =operator ueberladen worden ist?



  • Obwohl memcpy eine Option ist, wollte ich es einfach mal wissen. Natuerlich ist das jetzt kein repraesentativer Benchmark, aber soweit entfernt von Java liegt C++ ohne als auch mit Optimierung nicht (32 bit System).

    g++ main.cpp: time ./a.out -> user 0m0.512s (so ganz ohne Optimierung)
    g++ -O main.cpp: time ./a.out -> user 0m0.212s (mit Optimierung)
    java -Xms512m -Xmx1024m Test -> 386 ms

    Interessanterweise wollte die JVM das Programm nicht ohne maximaler Heapsize von 1024 MByte starten. Dabei wurde das entsprechende Javapaket von Sun genutzt.

    C++ kommt irgendwie auf zeiger zurück. strings, arrays, jede datenstruktur. und das ist eben das problem

    Ja und Nein. Bei einer Stringzuweisung weiss ich, dass diese zwei Strings keinen gemeinsamen Speicher benutzen, ausser es handelt sich um das gleiche Objekt. Daher kann ich z.B. das Kopieren auch per Hand parallelisieren. Das gleich gilt fuer Arrays (als Typ).

    Java- und C++-Programme:

    class Test
    {
        public static void main(String[] args)
        {
            int n = 100000000;
            int i = 0;
            int a1[] = new int[n];
            int a2[] = new int[n];
            long time = System.currentTimeMillis();
            while(i<n)
            {
                a1[i] = a2[i];
                ++i;
            }
            System.out.println( System.currentTimeMillis() - time );
        }
    }
    
    const int n = 100000000;
    int a1[n];
    int a2[n];
    
    int main()
    {
        int i = 0;
        while(i<n)
        {
            a1[i] = a2[i];
            ++i;
        }
        return 0;
    };
    


  • Shade Of Mine schrieb:

    knivil schrieb:

    Nur zur Klarstellung: Was, wie und in welchem Massstab bedeutet hier parallelisieren? UV-Pipeline, Mehrkern, ... ?

    Jede Art von Parallelisierung.

    Das ist doch Unsinn. Es geht hier um die fehlende Möglichkeit Mikrooptimierungen durch den Compiler vorzunehmen. Will man ein Programm richtig parallelisieren, muß man egal in welcher Sprache ganz massiv von Hand eingreifen.

    Shade Of Mine schrieb:

    Es ist aber so. In gewissen Situationen wird Java immer schneller sein als C++.

    Wenn man sein Compilerhandbuch zum Thema Parallelisierung gelesen hat, dann kann man das getrost als Unsinn bezeichnen. Java bietet von Haus einige wenige Möglichkeiten, so daß der Compiler Mikrooptimierungen vornehmen kann, die man bei C++ via Pragmas ebenfalls vornehmen kann.



  • ~john schrieb:

    Shade Of Mine schrieb:

    knivil schrieb:

    Nur zur Klarstellung: Was, wie und in welchem Massstab bedeutet hier parallelisieren? UV-Pipeline, Mehrkern, ... ?

    Jede Art von Parallelisierung.

    Das ist doch Unsinn. Es geht hier um die fehlende Möglichkeit Mikrooptimierungen durch den Compiler vorzunehmen. Will man ein Programm richtig parallelisieren, muß man egal in welcher Sprache ganz massiv von Hand eingreifen.

    Wenn ein Compiler eine längere Schleife parallelisieren kann und dadurch Faktor 2 oder mehr rausholen kann sehe ich das nicht mehr wirklich als Mikrooptimierung. So oder so, "Unsinn" ist das nicht.



  • DEvent schrieb:

    +fricky schrieb:

    Shade Of Mine schrieb:

    while(i<N) {
      trg[i]=src[i]);
      ++i;
    }
    

    das ist in java nämlich parallelisierbar. und es gibt nichts dass du in c++ tun kannst...

    doch, memcpy() nehmen.
    🙂

    Und wenn der =operator ueberladen worden ist?

    dann haste pech, oder geschwindigkeit ist sowieso egal.

    knivil: für solche kopierorgien gibts unter Java 'System.arraycopy()'.
    🙂



  • 90:10 sag ich da nur zu euch Mikrooptimisten.



  • Tim schrieb:

    Wenn ein Compiler eine längere Schleife parallelisieren kann und dadurch Faktor 2 oder mehr rausholen kann sehe ich das nicht mehr wirklich als Mikrooptimierung. So oder so, "Unsinn" ist das nicht.

    Du holst mit so einem Fliegensch* niemals den Faktor zwei heraus! Erstmal muß man die Laufzeit in dieser Routine mit der Gesamtlaufzeit der Applikation in Relation setzen. Wenn es sich um eine wirklich kritische Routine handelt, dann kann man diese optimieren. Aber dann wird man das grundsätzlich von Hand machen und nicht dem Compiler überlassen.



  • Tim schrieb:

    ~john schrieb:

    Shade Of Mine schrieb:

    knivil schrieb:

    Nur zur Klarstellung: Was, wie und in welchem Massstab bedeutet hier parallelisieren? UV-Pipeline, Mehrkern, ... ?

    Jede Art von Parallelisierung.

    Das ist doch Unsinn. Es geht hier um die fehlende Möglichkeit Mikrooptimierungen durch den Compiler vorzunehmen. Will man ein Programm richtig parallelisieren, muß man egal in welcher Sprache ganz massiv von Hand eingreifen.

    Wenn ein Compiler eine längere Schleife parallelisieren kann und dadurch Faktor 2 oder mehr rausholen kann sehe ich das nicht mehr wirklich als Mikrooptimierung. So oder so, "Unsinn" ist das nicht.

    Du hast doch keine Ahnung.


Anmelden zum Antworten