The "C is Efficient" Language Fallacy



  • maximAL schrieb:

    Allerdings wird in Java ja auf jeden nicht-primitiven Typen per Referenz zugegriffen, was das Problem gegenüber C++ wieder verstärkt.

    Das ist egal. Wichtig ist nur, dass der Compiler über die Referenzen viel strengere Annahmen treffen darf, als ein C- oder C++-Compiler über die Pointer/Referenzen. Die Situation wurde in C99 mit strict aliasing und restrict sicher verbessert. Aber nicht umsonst bezeichnet man C als portablen Assembler. Über viele Dinge kann der Compiler nur sehr wage Annahmen treffen und vieles liegt am Programmierer (zB restrict). Und in C++0x wird restrict leider noch nicht einmal aufgenommen.

    Aber im Endeffekt ist das optimieren von Highlevelcode eben ein schwieriges Problem, selbst mit der Möglichkeit gute Annahmen treffen zu können, wie man in den ganzen "Benchmarks" sieht.



  • rüdiger schrieb:

    Und in C++0x wird restrict leider noch nicht einmal aufgenommen.

    Warum eigentlich? Da hat man so viel eingebaut, aber solch eine elementare Geschichte nicht? Zumal viele Compilerbauer das wohl (dank C99) eh in petto hätten. Wundert mich schon ein wenig.



  • Tim schrieb:

    rüdiger schrieb:

    Und in C++0x wird restrict leider noch nicht einmal aufgenommen.

    Warum eigentlich? Da hat man so viel eingebaut, aber solch eine elementare Geschichte nicht? Zumal viele Compilerbauer das wohl (dank C99) eh in petto hätten. Wundert mich schon ein wenig.

    C != C++



  • Tim schrieb:

    Wundert mich schon ein wenig.

    die korrekte anwendung von 'restrict' liegt voll in der veantwortung des programmierers, sonst haste schnell undefiniertes verhalten. 'trust the programmer' scheint aber nicht so das ding von C++ zu sein, eher gefahrenqullen von vorn herein auszuschliessen.
    🙂



  • +fricky schrieb:

    scheint

    Wenn man keine Ahnung von C++ hat, dann "scheint" das so zu sein, ja.



  • aufmerksamer_leser schrieb:

    Tim schrieb:

    rüdiger schrieb:

    Und in C++0x wird restrict leider noch nicht einmal aufgenommen.

    Warum eigentlich? Da hat man so viel eingebaut, aber solch eine elementare Geschichte nicht? Zumal viele Compilerbauer das wohl (dank C99) eh in petto hätten. Wundert mich schon ein wenig.

    C != C++

    Und grün != braun. Was soll mir das in diesem Kontext sagen?



  • Basher schrieb:

    +fricky schrieb:

    scheint

    Wenn man keine Ahnung von C++ hat, dann "scheint" das so zu sein, ja.

    was wäre denn für dich ein plausibler grund?

    Basher schrieb:

    knivil schrieb:

    ...

    ...
    Aber da alle anderen schon auf den Artikel eingeprügelt haben und man sicherheitshalber einen Tag gewartet hat, ob noch was kommt, darf man ja unqualifiziert mit einstimmen

    übrigens machste deinem namen wieder mal alle ehre, lässt keine möglichkeit aus, jemanden dumm anzupöbeln.
    🙂



  • +fricky schrieb:

    was wäre denn für dich ein plausibler grund?

    Wenn dich C++ interessiert, informiere dich selbst. Ich werde das nicht für dich übernehmen.



  • Bashar schrieb:

    Wenn dich C++ interessiert, informiere dich selbst. Ich werde das nicht für dich übernehmen.

    sag doch gleich, dass du es nicht weisst.
    🙂



  • Es reicht doch, dass du es nicht weißt, aber trotzdem große Töne spuckst.



  • Tim schrieb:

    rüdiger schrieb:

    Und in C++0x wird restrict leider noch nicht einmal aufgenommen.

    Warum eigentlich? Da hat man so viel eingebaut, aber solch eine elementare Geschichte nicht? Zumal viele Compilerbauer das wohl (dank C99) eh in petto hätten. Wundert mich schon ein wenig.

    Ja, das wundert/enttäuscht mich auch. Einige Compiler bieten restrict ja schon in C++ an (GCC, Intel etc.).



  • rüdiger schrieb:

    maximAL schrieb:

    Allerdings wird in Java ja auf jeden nicht-primitiven Typen per Referenz zugegriffen, was das Problem gegenüber C++ wieder verstärkt.

    Das ist egal. Wichtig ist nur, dass der Compiler über die Referenzen viel strengere Annahmen treffen darf, als ein C- oder C++-Compiler über die Pointer/Referenzen.

    Begründung? In Java gibts zwar kein Aliasing mit unterschiedliche Typen, aber nichtsdestotrotz können durchaus mehrere Referenzen in einem Kontext auf das selbe Objekte verweisen, was die Arbeit für den Compiler erschwert.



  • maximAL schrieb:

    In Java gibts zwar kein Aliasing mit unterschiedliche Typen, aber nichtsdestotrotz können durchaus mehrere Referenzen in einem Kontext auf das selbe Objekte verweisen, was die Arbeit für den Compiler erschwert.

    einen grossteil der optimierung macht die java-VM zur laufzeit, nicht der compiler. damit hat Java natürlich sehr viel mehr optimiermöglichkeiten, als programmiersprachen, deren compiler starren maschinencode für bestimmte CPUs erzeugen müssen. http://en.wikipedia.org/wiki/Java_performance#Adaptive_optimization
    🙂



  • maximAL schrieb:

    Begründung? In Java gibts zwar kein Aliasing mit unterschiedliche Typen, aber nichtsdestotrotz können durchaus mehrere Referenzen in einem Kontext auf das selbe Objekte verweisen, was die Arbeit für den Compiler erschwert.

    Worum es geht ist, dass

    while(*a++=*b++);

    nicht parallelisierbar ist.

    das problem hast du in java nicht.


  • Administrator

    maximAL schrieb:

    Begründung? In Java gibts zwar kein Aliasing mit unterschiedliche Typen, aber nichtsdestotrotz können durchaus mehrere Referenzen in einem Kontext auf das selbe Objekte verweisen, was die Arbeit für den Compiler erschwert.

    Hmmm, kenne mich zwar nicht so gut aus, aber wenn ich nach dem Wikipedia Artikel gehe, dann steht als Beispiel dies hier:

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

    Problem ist ja, dass lhs und val auf das gleiche Verweisen können. Also muss der Wert von val neu geladen werden, bevor die nächste Rechnung durchgeführt werden kann.

    Bei Java sieht dies allerdings etwas anders aus:

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

    val wird hier unverändert bleiben, egal wie man die Funktion aufruft.

    Würde das aber gerne noch bestätigt bekommen, bin mir nicht sicher, ob ich es ganz getroffen habe 🙂

    Grüssli



  • Dravere schrieb:

    maximAL schrieb:

    Begründung? In Java gibts zwar kein Aliasing mit unterschiedliche Typen, aber nichtsdestotrotz können durchaus mehrere Referenzen in einem Kontext auf das selbe Objekte verweisen, was die Arbeit für den Compiler erschwert.

    Hmmm, kenne mich zwar nicht so gut aus, aber wenn ich nach dem Wikipedia Artikel gehe, dann steht als Beispiel dies hier:

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

    Problem ist ja, dass lhs und val auf das gleiche Verweisen können. Also muss der Wert von val neu geladen werden, bevor die nächste Rechnung durchgeführt werden kann.

    Bei Java sieht dies allerdings etwas anders aus:

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

    val wird hier unverändert bleiben, egal wie man die Funktion aufruft.

    Würde das aber gerne noch bestätigt bekommen, bin mir nicht sicher, ob ich es ganz getroffen habe 🙂

    Grüssli

    Abgesehen davon, dass dein Java Beispiel semantisch etwas völlig anderes tut, ja.



  • In java sind ints genau so wenig Referenztypen, das Verhalten ist also genau das selbe, wie wenn du in C++ die ints per Val übergibst.
    Wenn du Referenztypen aus Java nimmst können die dann aber wiederum auch auf das selbe zeigen.


  • Administrator

    JustAnotherNoob schrieb:

    In java sind ints genau so wenig Referenztypen, das Verhalten ist also genau das selbe, wie wenn du in C++ die ints per Val übergibst.
    Wenn du Referenztypen aus Java nimmst können die dann aber wiederum auch auf das selbe zeigen.

    Ich muss zugeben, dass mein Java völlig eingerostet ist, aber wenn ich es korrekt in Erinnerung hatte, dann wird hier nicht per Value übergeben sondern per Referenz. Intern bei der Addition wird das Ergebnis nicht in die referenzierte Variable geschrieben, sondern eine neue erstellt und diese dann der Referenz zugewiesen. Die Referenzen lhs und rhs werden also in der Funktion auf zwei neue Variablen gesetzt und zwar jeweils nach der Addition.

    Das gleiche gilt dann auch bei anderen Objekten in Java wie zum Beispiel java.lang.String . Bei jeder Veränderung wird einem gleich ein neues Objekt zurückgeliefert. Die Veränderungen werden also nicht auf dem Objekt selbst durchgeführt.

    Kann gut sein, dass ich hier völlig auf dem Holzweg bin, wie gesagt, mein Java ist eingerostet. Würde mich aber freuen, wenn mich da jemand korrigieren könnte, falls ich falsch liege.

    Grüssli



  • aber wenn ich es korrekt in Erinnerung hatte, dann wird hier nicht per Value übergeben sondern per Referenz.

    http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html
    -> nein, das wird nicht als Referenz übergeben.

    String ist nochmal ein Sonderfall, weil es ein Objekt ist, dass von Literalen erzeugt wird, aber normale Objekte können durchaus aufeinander verweisen, mit

    Object a = new Object();
    Object b = a;
    

    verweist b afaik auf a.



  • Dravere schrieb:

    JustAnotherNoob schrieb:

    In java sind ints genau so wenig Referenztypen, das Verhalten ist also genau das selbe, wie wenn du in C++ die ints per Val übergibst.
    Wenn du Referenztypen aus Java nimmst können die dann aber wiederum auch auf das selbe zeigen.

    Ich muss zugeben, dass mein Java völlig eingerostet ist, aber wenn ich es korrekt in Erinnerung hatte, dann wird hier nicht per Value übergeben sondern per Referenz. Intern bei der Addition wird das Ergebnis nicht in die referenzierte Variable geschrieben, sondern eine neue erstellt und diese dann der Referenz zugewiesen. Die Referenzen lhs und rhs werden also in der Funktion auf zwei neue Variablen gesetzt und zwar jeweils nach der Addition.

    Das gleiche gilt dann auch bei anderen Objekten in Java wie zum Beispiel java.lang.String . Bei jeder Veränderung wird einem gleich ein neues Objekt zurückgeliefert. Die Veränderungen werden also nicht auf dem Objekt selbst durchgeführt.

    Kann gut sein, dass ich hier völlig auf dem Holzweg bin, wie gesagt, mein Java ist eingerostet. Würde mich aber freuen, wenn mich da jemand korrigieren könnte, falls ich falsch liege.

    Grüssli

    Java ist wie C und C++ auch "call by Value", sprich die Parameter werden immer kopiert. In Java werden die primitiven Typen aber auch wie in C und C++ gehandhabt und nicht wie die Java-Objekte (beidenen ist nur Zugriff über Zeiger möglich).


Anmelden zum Antworten