Programm unter Win schneller als unter Lin ?!



  • Schonmal dran gedacht das deine Sekundenzahl nicht stimmt.
    Es vergehen bei 4 - 200000 Intel 2.5 GHZ 135 Sekunden obwohl nur 60 angezeigt werden.
    Weiters darfst du auch nicht die Ausgabe dazurechnen.

    [ Dieser Beitrag wurde am 22.04.2003 um 06:46 Uhr von Unix-Tom editiert. ]



  • Hi,

    also ohne fuer den Athlon optimiert zu haben, sind es bei mir 125sec, wenn man
    den Anzeigen trauen darf. Werde heute mal noch fuer den Athlon optimieren lassen.

    Mein System:

    AMD Athlon XP 2200+ M
    512MB DDR
    OS: FreeBSD 5.0-RELEASE Customer Kernel

    mfg
    v R



  • nice -20 ./code
    ?



  • wollt nochmal was zu den optimierungen sagen:
    (system: PI 200, 96 Räm, 2.4.19 kernel, intervall 4 - 25000, bei 200000 hats 1250 sec gedauert [bei O3])

    ohne optimierung: 26.650 sec
    O2: 21.320 sec
    O3: 21.320 sec (komisch, was? habs aber mehrfach ausprobiert)
    O4: 21.350 sec

    irgendwie lohnt also nur die O2, bei den anderen steigt nur noch die programmgröße, hatte alerdings keine großen zahlen (mache den test grad noch)



  • Original erstellt von Unix-Tom:
    **Schonmal dran gedacht das deine Sekundenzahl nicht stimmt.
    Es vergehen bei 4 - 200000 Intel 2.5 GHZ 135 Sekunden obwohl nur 60 angezeigt werden.
    Weiters darfst du auch nicht die Ausgabe dazurechnen.

    [ Dieser Beitrag wurde am 22.04.2003 um 06:46 Uhr von [qb]Unix-Tom** editiert. ][/QB]

    ??? Bei mir vergehen genauso viel Sekunden wie angezeigt werden, also ist da alles in bester Ordnung. Außerdem rechne ich keine Ausgabe dazu, die eine "Verstoß gegen die Goldbach-Vermutung" tritt nie auf, da die Vermutung für alle geraden Zahlen größer 2 zutreffen müsste. Und die anderen Ausgaben folgen erst nach dem Stoppen der CPU-Zeit mit ende=clock()!



  • Original erstellt von HAR:
    nice -20 ./code
    ?

    Hab ich ausprobiert, da aber keine weiteren rechenintensiven Prozesse laufen, hat das nicht wirklich etwas gebracht...



  • Die richtigen Compiler Einstellungen sind schon mal ganz wichtig.
    Lediglich mit -O1 oder -O2 (-O3 bringt nichts bis nicht mehr viel) ist die Laufzeit schon einmal kürzer. Wenn ich dann noch weitere Compiler Optionen angebe, steigert sich die Performance auf Faktor 3:

    O0: 538.030 Sek (ohne Optimierung)
    O1: 462.100 Sek
    O2: 462.620 Sek
    O2: 185.470 Sek (mit zusätzlichen Compiler Optionen)

    $ gcc --version
    gcc (GCC) 3.1
    Copyright (C) 2002 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions. There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    $ uname -a
    SunOS 5.8 sun4us sparc FJSV,GPUS

    $ gcc -o main_goldbach_opti -Wall -Wmain -std=c99 -O2 -fsigned-char -fno-asm -fno-builtin -finline-functions -fomit-frame-pointer -m64 -mptr64 -mhard-float -mfpu -mcpu=v9 main_goldbach.c

    Die Laufzeit deines Programms skaliert quadratisch zur Anzahl der zu testenden Zahlen. Vielleicht solltest du da mal was dran drehen.

    In nachfolgendem Quellcode habe ich deine Goldbach Testroutine durch Funktionen von Armand Turpel ersetzt. Im Interval [4...200000] erhalte ich eine Laufzeit von 2.270 Sek wenn ich die Ausgabe in eine Datei umleite. Allerdings ist noch irgendwo ein Bug -- die 4 wird als Fehler aufgezeigt.

    am_* Funktionen der "C-lib of math routines" von Armand Turpel entnommen
    http://www.2357.a-tu.net/index.php?link=Software

    #include <stdio.h>
    #include <math.h>
    #include <time.h>
    
    int p_pt(int t)
    {
      int a=5;
      while (a*a<=t)
        {
          if (t%a==0)
            return -1;
          if (t%(a+2)==0)
            return -1;
          a=a+6;
        }
      return 1;
    }
    
    /* do we have a prime number ? */
    int am_primetest(int t)
    {
      int a=5;
      if (t<4)
        {
          if (t==2)
            return 1;
          if (t==3)
            return 1;
          return -1;
        }
      if (t%2==0)
        return -1;
      if (t%3==0)
        return -1;
      while (a*a<=t)
        {
          if (t%a==0)
            return -1;
          if (t%(a+2)==0)
            return -1;
          a=a+6;
        }
      return 1;
    }
    
    /*  Goldbach's Conjecture  */
    int am_goldbach(int a,int *p)
    {
      int e=5,k;
      if (am_primetest(a-3)==1)
        {
          p[0]=3;
          p[1]=a-3;
          return 1;
        }
      k=a/2+1;
      while(e<k)
        {
          if (p_pt(e)==1)
            {
              if(am_primetest(a-e)==1)
                {
                  p[0]=e;
                  p[1]=a-e;
                  return 1;
                }
            }
          e=e+2;
          if (p_pt(e)==1)
            {
              if(am_primetest(a-e)==1)
                {
                  p[0]=e;
                  p[1]=a-e;
                  return 1;
                }
            }
          e=e+4;
        }
      return -1;
    }
    
    int main(void)
    {
      int von, bis, i;
      clock_t start, ende;
      int buffer[2];
    
      printf("Goldbach-Vermutung\n"
             "==================\n\n"
             "-> Jede gerade Zahl groeßer als 2 ergibt sich aus der Summe\n"
             "   zweier Primzahlen... - dies ueberprueft das Programm\n\n");
      printf("Zu pruefenden Bereich eingeben:\n");
    
      do
        {
          printf("1. Untere Grenze: ");
          scanf("%ld", &von);
        }
      while(von<0 && printf("Zahl muss positiv sein!\n"));
      printf("2. Obere Grenze: ");
      scanf("%ld", &bis);
    
      start = clock();
    
      /* pruefe alle Zahlen im Bereich [von...bis] */
      for(i=von; i<=bis; i+=2)
        {
          if ( am_goldbach(i,buffer) == -1)
            {
              printf("Goldbach's conjecture is wrong. ( %i )\n", i);
            }
          else
            {
              printf("Goldbach is right: %i = %i + %i\n", i, buffer[0], buffer[1]);
            }
        }
    
      ende = clock();
    
      printf("\nAlle Zahlen im Bereich [%ld...%ld] entsprechen "
             "der Goldbach-Vermutung!\n\n", von, bis);
      printf("Benoetigte Zeit: %10.3f Sek\n\n",
             (ende-start)/(double)CLOCKS_PER_SEC);
    
      return 0;
    }
    


  • Nicht schlecht, Descartes, der neue Algorithmus, allerdings geht es mir nicht um eine Verbesserung dessen sondern doch nur um eine Verbesserung der Geschwindigkeit unter Linux, welche im Vergleich zu Windows bei gcc -Wall -O2 ja nicht wirklich gut abschneidet. Trotzdem danke für diesen neuen Weg...



  • Mal ein paar "Kontrollwerte" , die gleichzeitig auch Fragen aufwerfen:

    Athlon XP 1600+ (1400MHz), Code aus Mellons erstem Beispiel, Bereich von 4 bis 100000 (Einhunderttausend).

    Borland C++ Builder 6, WinXP, Debug-Modus, keine Optimierungen: ~45 sec
    Borland Kylix3, SuSE 8.1, Debug-Modus, keine Optimierungen, KDE-Konsole: ~48 sec

    Die angezeigten Zeiten decken sich mit Handmessungen.

    Fragen wirft das Ganze deshalb auf, weil der Rechner doch deutlich langsamer ist, aber nur rund die Hälfte der besten Zeit von Mellon benötigt. Welchen "Borland C-Compiler" genau hast du denn da benutzt?

    Nachtrag:
    SuSE 8.1, gcc -Wall -O2, KDE-Konsole: ~42 sec

    [ Dieser Beitrag wurde am 22.04.2003 um 14:50 Uhr von Jansen editiert. ]



  • Original erstellt von Jansen:
    **
    Fragen wirft das Ganze deshalb auf, weil der Rechner doch deutlich langsamer ist, aber nur rund die Hälfte der besten Zeit von Mellon benötigt. Welchen "Borland C-Compiler" genau hast du denn da benutzt?
    **

    Hatte oben geschrieben, dass ich mich erst vertippt hatte. Es gilt das Intervall [4...200000] für die gemessenen Zeiten.

    Tw: Kann mir einer sagen, welche gcc-Optionen für meinen XP 2400+ am besten wären?! Auch mit "gcc -O2 -Wall -Wmain -fsigned-char -fno-asm -fno-builtin -finline-functions -fomit-frame-pointer -o goldbach goldbach.c" komme ich nicht unter 127 Sekunden und da ist Win ja immernoch 20 Sekunden schneller!
    😞



  • gcc -Wall -W -pipe -O3 -fomit-frame-pointer -malign-double -fschedule-insns2 -march=athlon -mcpu=athlon -malign-functions=4

    beim gcc 3.2.1 > solltest du auch mal die Option -mfpmath=sse,387 ausprobieren

    (und du solltest vielleicht lieber einen Profiler benutzen, anstelle intern die Geschwindigkeit zu messen)

    [ Dieser Beitrag wurde am 22.04.2003 um 16:30 Uhr von kingruedi editiert. ]



  • Original erstellt von kingruedi:
    **gcc -Wall -W -pipe -O3 -fomit-frame-pointer -malign-double -fschedule-insns2 -march=athlon -mcpu=athlon -malign-functions=4

    beim gcc 3.2.1 > solltest du auch mal die Option -mfpmath=sse,387 ausprobieren
    **

    Tja, selbst damit komme ich nur auf 119 Sekunden. Das sind immernoch 12 Sekunden zu langsam im Gegensatz zu Windows. Und: bei Windows läuft das GUI, bei Linux nur die Konsole. Ich bin aber Linux-Anhänger und will nun endlich mal wissen, wie sich diese Differenz erklären lässt. Compiler unter Windows war übrigens der "Borland C 5.0"...



  • mess die Geschwindigkeit am besten mal mit einem Profiler nach, anstelle interner Zeitanalyse.



  • Sorry: Profiler?! 😕



  • Siehe z.B. Manpage gprof(1)

    1.) Programm kompilieren mit der GCC Option "-pg"

    2.) Kompilierte Programm einmal ausführen (es wird eine Datei "gprof.mon" erzeugt)

    3.) den Profiler aufrufen: gprof goldbach.exe gprof.mon"

    Steht aber alles auch in der Manpage gprof(1)

    Profiling, Linker-Mapdateien und obskure gcc-Optionen unter Linux
    http://www.fefe.de/devel/profiling.txt



  • Hat etwas länger gedauert.
    Also: ich habe das mit gprof mal gemacht, funzt auch gut. Habe den Code zwischen den beiden clock()-Aufrufen in eine eigene Funktion gepackt, so dass ich deren Zeit abrufen kann. Unter debian sowie suse braucht das Programm 113 Sekunden. Habe es auch nochmal ohne Profiling in Windows XP gemacht. Dort braucht es jetzt 115 Sekunden (obwohl ich nichts geändert habe 8 Sekunden langsamer?! naja...), das bezieht sich aber auf die clock()-Aufrufe und die Zeitberechnung damit. Gibt es auch einen Profiler unter Windows, der ähnlich gprof ist? Und was ist der Unterschied zwischen Abrufen mit clock() oder mit gprof? Mit den clock()-Abrufen komme ich auf ca. 119 Sekunden, also 6 Sekunden langsamer, obwohl es derselbe Codeteil ist. Auch im Vergleich zu Windows ist es hier wieder langsamer. Sind Lin und Win bei clock() eigentlich äquivalent anzusehen?
    Unter tomsrtbt habe ich es auch mal ohne gprof probiert: 113 Sekunden! Soll heißen, mit gprof wäre es noch weniger geworden - kein Wunder auch, wenn fast kein Prozess am Laufen ist...
    Hätte jetzt aber mal gern eine Aufklärung zu o.a. Fragen, das Ganze wurmt mich immernoch recht doll.



  • die Unterschiede bei clock lassen sich wahrscheinlich darauf zurückführen, dass die Intel Hardware wohl nur alle paar ms ein Zeitsignal schickt und somit eh keine genauen Messungen zulässt.



  • Trotzdem wäre in diesem Fall Win immernoch schneller als ein Konsole-debian 3.0! Also von den clock()-Werten ausgehend und die dürften ja wegen ANSI-C-Norm auf Linux und Windows gleich behandelt werden, nicht? Das Ganze muss doch einen Grund haben?!



  • Ist es denn zu abwegig, zu glauben, dass Hersteller proprietärer Compiler einfach eher (Stichwort: NDA) an Informationen von Intel kommen, als ein Projekt wie z.B. die GNU Compiler Collection?`

    Ist es darüber hinaus abwegig, zu glauben, dass ein Compiler der *ausschliesslich* auf der Intel Architektur arbeitet, optimierteren Code erzeugt als z.B. die GNU Compiler Collection, die nebenbei auch auf HP-PARISC, PowerPC, M68K, DEC Alpha, ... lauffähig ist und auch für die dortige CPUs Crosscompilieren kann?



  • Soll das heißen (j/n), dass Linux im ANSI-C-Vergleich zu Windows langsamer ist, da doch soviel unter Linux mit gcc kompiliert ist?

    Es ist nicht abwegig, nein, und der gcc ist ja auch nicht dafür bekannt, den saubersten Maschinencode zu erzeugen. Mich stört es bloß zu glauben, dass deswegen das komplette Linux langsamer ist als es sein könnte...


Anmelden zum Antworten