was muss ein Progammierer können?



  • Mir fällt da grad noch etwas ein, was Programmierer können sollten:

    Sie sollten die Programme die sie benutzen auch bedienen können! Die wenigsten die ich kenne beherrschen ihre Programme und reizen deren Leistungspotential aus.

    Viele Grüße
    Stefan



  • Wenn man Interesse und Spass am programmieren hat wird man auch Interesse am Computer bzw. an der Hardware haben und gut kann in einem Gebiet kann man nur sein wenn man sich dafür begeistert und wie bereits erwähnt wer sich dafür begeistert wird sich auch über die Hardware informieren.
    Und wenn man bemüht ist immer das letzte aus seinen Programmen rasuzuholen dann
    kommt man auch da nicht vorbei.

    Theoretisch kann man auch super Programme schreiben ohne zu Wissen wie eine verkette Liste funktioniert bzw. ohne ein "Algorithmen in ..." Buch zu besitzen, weil es das meist schon in der Standardlib gibt bzw. es genug freie Bibliotheken im Web gibt.



  • Ich denke dass wichtigste was einen Programmierer ausmacht, ist die Fähigkeit seinen eigenen Code zu verstehen.
    Es ist erstaunlich wieviele Leute irgendwelche Programmzeilen aus dem Tutorial X, oder der Seite Y nehmen und einfach nur "copien&pasten". Dass das in die Hose geht ist eigentlich immer garantiert.

    Aber auch beim Bugfinding probieren viele einfach nur *irgendwas* aus. x+=2 klappt net ?? machen wir daraus ein x+=3. Klappt nicht ? Hmm, wie siehts mit x+=4 aus ?
    Fehlermachen ist wichtig ! Durch Fehler lernt man was wie man bestimmte Fallstricke meidet und umgeht, und vor allem : Man lernt wies NICHT geht 🙂 Durch simples rumprobieren (Prinzip Trial&Error) geht dieser Effekt verloren.

    [edit]

    Orginal erstellt von Mahatma Ghandi
    If you loose, don't loose the lesson

    [/edit]

    [ Dieser Beitrag wurde am 03.01.2003 um 20:05 Uhr von Headhunter editiert. ]



  • @ Ste.fun : Hier ein einfaches Beispiel, das zeigt, dass man mit generellen Hardware-Kenntnissen besseren (schnelleren) Code schreibt (in Java). ...so groß ist der Gewinn hier aber nicht (nur etwas mehr als 10%) :
    [java]
    public class Test
    {
    public static void main (String [] args)
    {
    int size = 150000;
    System.out.println ("Variante 1 :");
    long time = System.currentTimeMillis();
    {
    int [] values = new int [size];
    for (int i = 0 ; i < 20000 ; ++i)
    {
    for (int j = 0 ; j < size ; ++j)
    {
    ++values[j];
    }
    }
    int a = 0;
    for (int j = 0 ; j < size ; ++j)
    {
    a += values [j];
    }
    System.out.println ("Zahl : " + a);
    }
    System.out.println ("Zeit : " + (System.currentTimeMillis() - time));
    System.out.println ("Variante 2 :");
    time = System.currentTimeMillis();
    {
    int [] values = new int [size];
    for (int j = 0 ; j < size ; ++j)
    {
    for (int i = 0 ; i < 20000 ; ++i)
    {
    ++values[j];
    }
    }
    int a = 0;
    for (int j = 0 ; j < size ; ++j)
    {
    a += values [j];
    }
    System.out.println ("Zahl : " + a);
    }
    System.out.println ("Zeit : " + (System.currentTimeMillis() - time));
    }
    }[/code]
    Ausgabe bei mir :

    Variante 1 :
    Zahl : -1294967296
    Zeit : 28060
    Variante 2 :
    Zahl : -1294967296
    Zeit : 24906



  • @Gregor: Füge bei size nochmal 2 Nullen an *g*. Wenn die JRT das mitmacht ein geiler Test.



  • @Gregor:
    Danke für das nette Beispiel! Auf meiner Maschine war der Geschwindigkeitsvorteil sogar knapp 100%!!

    Variante 1 :
    Zahl : -1294967296
    Zeit : 113857
    Variante 2 :
    Zahl : -1294967296
    Zeit : 58300

    Viele Grüße
    Stefan



  • ...ich habe die Taktfrequenz erhöht und eine 0 angehängt!

    Ausgabe :

    Variante 1 :
    Zahl : -64771072
    Zeit : 208830
    Variante 2 :
    Zahl : -64771072
    Zeit : 167210

    ...mehr Zeit nehm ich mir dafür nicht. Wenn einer seinen Rechner mal ne Nacht lang damit beschäftigen will, dann kann er size ja noch weiter erhöhen. Wenn die JVM zu wenig Speicher bereitstellt, dann startet er das ganze einfach mit

    java -Xmx192m Test

    ...oder mit einer anderen Zahl statt 192. Diese Zahl gibt den maximal belegbaren Speicher an.

    ...wenn die Array-Größe mehr Speicher braucht, als RAM da ist, dann sollte Variante 1 noch deutlich langsamer werden. 🙂



  • Hab grad nochmal ein paar Testläufe gestartet. Keine Ahnung wie der Rechner auf die 100%-ige Geschwindigkeitsteiguerung kam. Feststeht, dass Variante2 auf jedenfall schneller ist. Bei mir um 20-30%.

    Viele Grüße
    Stefan

    PS: Ich gebe mich ja geschlagen, ein Programmierer sollte auch gute Hardwarekenntnisse haben... *böseblickezumarc++usundgregorwerf* 😉



  • Ich hab das auch mal probiert, ist ja erstaunlich, was das für einen Unterschied macht (bei mir auch 30%). Falls es sonst noch jemand mal auf die Schnelle ausprobieren will hab ich mal ein Applet dazu gemacht, mit drei verschiedenen größen von size:
    1500000



  • Ein quick&dirty Hack:

    include <iostream>
    #include <time.h>
    
    int main() {
        const int N = 150000, M = 20000;
    
        int a[N];
    
        clock_t t = clock();
    
        int i, j;
    
        int x = 0;
    
        for (i = 0; i < M; i++) 
            for (j = 0; j < N; j++)
                x &= a[j]++;
    
        clock_t d = clock() - t;
    
        std::cout << "Zahl: " << x + a[20] << std::endl << "Zeit: " << d << std::endl;
    
        memset(a, 0, sizeof(a));
    
        t = clock();
        x = 0;
    
        for (i = 0; i < N; i++)
            for (j = 0; j < M; j++)
                x &= a[i]++;
    
        d = clock() - t;
    
        std::cout << "Zahl: " << x + a[20] << std::endl << "Zeit: " << d << std::endl;
    }
    

    Von der Komplexität vergleichbar mit dem Java-Programm.

    ergibt auf meinem Rechner diese Zahlen:

    Zahl: 20000
    Zeit: 29046
    Zahl: 20000
    Zeit: 5594
    

    Und ich musste meinen Compiler regelrecht davon abhalten, dafür zu sorgen dass bei Variante 2 bei Zeit nicht 0 steht. So ein C++ Compiler ist doch was feines *g*.

    Assembler Listing Variante 1 (der Quellcode hat durch die heftigen Optimierungen nur noch wenig Bedeutung):

    xor esi, esi
        mov edx, 20000              ; 00004e20H
    $L7399:
    
    ; 16   :        for (j = 0; j < N; j++)
    
        xor eax, eax
    $L7402:
    
    ; 17   :            x &= a[j]++;
    
        mov ecx, DWORD PTR _a$[esp+eax*4+600016]
        and esi, ecx
        inc ecx
        mov DWORD PTR _a$[esp+eax*4+600016], ecx
        inc eax
        cmp eax, 150000             ; 000249f0H
        jl  SHORT $L7402
    
    ; 14   : 
    ; 15   :    for (i = 0; i < M; i++) 
    
        dec edx
        jne SHORT $L7399
    

    Variante 2:

    xor esi, esi
        lea ecx, DWORD PTR _a$[esp+600016]
        mov edi, 150000             ; 000249f0H
    $L7588:
    
    ; 27   : 
    ; 28   :    for (i = 0; i < N; i++)
    ; 29   :        for (j = 0; j < M; j++)
    
        mov eax, DWORD PTR [ecx]
        mov edx, 20000              ; 00004e20H
    $L7591:
    
    ; 30   :            x &= a[i]++;
    
        and esi, eax
        inc eax
        dec edx
        jne SHORT $L7591
        mov DWORD PTR [ecx], eax
        add ecx, 4
        dec edi
        jne SHORT $L7588
    

    wäre da nicht das x &= -- der Compiler würde aus der ganzen for Schleife ein einziges += machen...

    [ Dieser Beitrag wurde am 04.01.2003 um 00:51 Uhr von Mr. N editiert. ]



  • @Daniel Schumann:
    "Var.2 schafft es in 101% der Zeit von Var.1"
    ...

    edit: nun sind es 92 🙂

    [ Dieser Beitrag wurde am 04.01.2003 um 01:00 Uhr von Noesis editiert. ]



  • @Noesis: dein Rechner muss einer im 166 MHz Bereich sein *fg*



  • Original erstellt von <manu>:
    Hallo!
    was muss ein Programmierer umbedingt können?

    ganz wichtig: kaffee kochen !!



  • hmm... ich hab mir grad den Thread durchgelesen.... ich seh zwischen den beiden Varianten eigntlich keinen Unterschied. Bin zwar müde, und beherrsche Java überhaupt net, aber auch im C++ - code fällt mir so auf den ersten Blick kein Unterschied auf. Worin liegt der jeweils? 😕

    zum Topic:
    ich würde sagen, das wichtigste, was der Programmierer an Voraussetzungen mitbringen muss, ist das Interesse am PC im Allgemeinen... weil alles andere sich normalerweise davon ableiten wird... 🙂

    [ Dieser Beitrag wurde am 04.01.2003 um 01:21 Uhr von Blue-Tiger editiert. ]



  • Schau dir die Schleife genau an. Und dann überleg dir beim java-code wie im Prozessor der L1-Cache aussieht und beim C++-Code, wie hier Register genutzt werden können.



  • Ich habe noch eine 3. Variante hinzugefügt :
    [java]
    public class Test
    {
    public static void main (String [] args)
    {
    int size = 150000;
    System.out.println ("Variante 1 :");
    long time = System.currentTimeMillis();
    {
    int [] values = new int [size];
    for (int i = 0 ; i < 20000 ; ++i)
    {
    for (int j = 0 ; j < size ; ++j)
    {
    ++values[j];
    }
    }
    int a = 0;
    for (int j = 0 ; j < size ; ++j)
    {
    a += values [j];
    }
    System.out.println ("Zahl : " + a);
    }
    System.out.println ("Zeit : " + (System.currentTimeMillis() - time));
    System.out.println ("Variante 2 :");
    time = System.currentTimeMillis();
    {
    int [] values = new int [size];
    for (int j = 0 ; j < size ; ++j)
    {
    for (int i = 0 ; i < 20000 ; ++i)
    {
    ++values [j];
    }
    }
    int a = 0;
    for (int j = 0 ; j < size ; ++j)
    {
    a += values [j];
    }
    System.out.println ("Zahl : " + a);
    }
    System.out.println ("Zeit : " + (System.currentTimeMillis() - time));
    System.out.println ("Variante 3 :");
    time = System.currentTimeMillis();
    {
    int [] values = new int [size];
    for (int j = 0 ; j < size ; ++j)
    {
    int tempValue = 0;
    for (int i = 0 ; i < 20000 ; ++i)
    {
    ++tempValue;
    }
    values [j] = tempValue;
    }
    int a = 0;
    for (int j = 0 ; j < size ; ++j)
    {
    a += values [j];
    }
    System.out.println ("Zahl : " + a);
    }
    System.out.println ("Zeit : " + (System.currentTimeMillis() - time));
    }
    }[/code]
    Ausgabe (mit erhöhter Taktfrequenz gegenüber dem allerersten Test):

    Variante 1 :
    Zahl : -1294967296
    Zeit : 19888
    Variante 2 :
    Zahl : -1294967296
    Zeit : 15903
    Variante 3 :
    Zahl : -1294967296
    Zeit : 6339

    Ich denke, um solche Optimierungen machen zu können, muss man schon etwas Hintergrundwissen über die Hardware etc. haben.

    [ Dieser Beitrag wurde am 04.01.2003 um 09:39 Uhr von Gregor editiert. ]



  • @Gregor: Is zwar OT aber daran sieht man, dass Java in der Hinsicht performance-technisch suckt. Mein C++ Code hat nämlich bereits für Variante 2 eine vergleichbare Zeit ausgegeben. Und wenn man das x &= weglässt hatte Variante 2 die sagenhafte Zeit von 0 Millisekunden *fg*. Sowas traut sich kein java-compiler :D. Wenn dir Hardware so wichtig ist, solltest du auf C++ (+ ASM *g*) umsteigen.



  • @ Mr. N : Ich habe mir eben mal MinGW runtergeladen und dein Programm auf höchster Optimierungsstufe kompiliert.

    Ergebnis :

    Zahl: 20000
    Zeit: 18616
    Zahl: 20000
    Zeit: 28431

    ...irgendwie ist das Ergebnis komisch. Zumindest scheint nicht jeder C++-Compiler so toll zu sein, wie der, den du nutzt.

    Allerdings hast du Recht. javac optimiert nicht so sehr, wie die meisten C++-Compiler. AFAIK werden zum Beispiel keine sinnlosen Schleifen wegoptimiert. Warum auch? Kein Programmierer wird (in realen Programmen) Schleifen programmieren, die eigentlich sinnlos sind. ...zumindest nicht in zeitkritischen Bereichen.



  • Gehen wir das Thema mal anders an, was ist ein Programmieren?

    PROGRAMMIERER, eine Person, die Computerprogramme schreibt und von Fehlern befreit.

    Ein Zitat aus Encarta (Microso**) ... kein wunder bei dem Satz:

    und von Fehlern befreit



  • Es gibt aber auch noch den Spruch:

    Wenn Debugging der Vorgang ist Fehler aus einem Programm zu entfernen,
    so ist Programmierung der Vorgang Fehler in ein Programm einzubauen.


Anmelden zum Antworten