Autor Beitrag
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Di 10.01.06 18:19 
Hi @all,

den Quelltext den ich hier habe, würde ich gerne noch ein bisschen optimieren (um schneller gegen die C und .NET-Entwicklung zu sein). Es geht hier bei um die Scuhe nach Primzahlen bis zu einer bestimmten Grenze.

Folgenden Quelltext nutzte ich momentan, der auch ziemlich schnell läuft (auf einem 3200er für 100. Mio. 23 Sek und auf einem 200er für 10 Mio. 5 Sek.; Messungen ohne Dateiausgabe, was aber nachträglich noch an die Aufgabenstellung hin zu gefügt wurde). Die Hauptoptimierung die hier noch erfolgen muss, ist der RAM-Verbrauch (durch einige Versuche habe ich es mit bekommen, dass es die langsamste Stelle allgemein noch ist [isses ja meistens]). Bei dem 200er ist das Problem, dass er nur 32 MB (oder waren es nur 16 MB? :gruebel: ) zur Verfügung haben. So hat er bei 100 Mio. auf einmal über eine Stunde gebraucht hat (dann hatte ich ihne abgebrochen ;) ). Theoretisch verbraucht er ja ca. 100 MB Speicher für 100 Mio. Boolean-Vars, wes wegen er Auslagerungsdateien mit nutzten musste. Allerdings könnte ich den Speicherverbrauch schon einmal halbieren, da ich jedes 2. Element sowieso nicht abfragen ( :arrow: schreiben müsste man dem entsprechend abfangen). Zur Optimierung könnte man das also heran ziehen bzw. dass ein Boolean nicht 1 Byte sondern 1 Bit verbraucht. Wie würdet ihr das machen bzw. was für Opti-Vorschläge habt ihr (und wie umgesetzt)?

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
program Project1;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  Classes;

var
  MaxPrim: Int64;
  PrimIndex: Int64;
  j, Anzahl: Int64;
  Prim: array of Boolean;
  T1, T2, T3: Int64;
  MemoryStream: TMemoryStream;
  FileStream: TFileStream;
  Buffer: String;

begin
  write('Primzahlen suchen bis (0=Beenden): ');
  readln(MaxPrim);
  while MaxPrim>0 do
  begin
    QueryPerformanceCounter(T1);
    MemoryStream:=TMemoryStream.Create;
    case MaxPrim of
      1: ;
      2: MemoryStream.Write('2'+#13#103);//Write('2');
      else
      begin
        MemoryStream.Write('2'+#13#103);//Write('2');
        SetLength(Prim, MaxPrim+1);
        PrimIndex:=3;
        FillChar(Prim[0], MaxPrim+1, false);
        PrimIndex:=3;
        Anzahl:=0;
        while PrimIndex<=MaxPrim do
        begin
          if Prim[PrimIndex]=false then
          begin
            j:=PrimIndex;
            inc(Anzahl);
            Buffer:=IntToStr(PrimIndex)+#13#10;
            MemoryStream.Write(Buffer[1], length(Buffer));
            //writeln(PrimIndex);
            while j+PrimIndex<=MaxPrim do
            begin
              inc(j, PrimIndex);
              Prim[j]:=true;
            end;
          end;
          inc(PrimIndex, 2);
        end;
        Setlength(Prim, 0);
      end
    end;
    writeln('Gefunden: '+IntToStr(Anzahl+1));
    FileStream:=TFileStream.Create('Prim_'+IntToStr(MaxPrim)+'.txt', fmCreate or fmOpenWrite);
    MemoryStream.Position:=0;
    FileStream.CopyFrom(MemoryStream, MemoryStream.Size);
    FreeAndNil(FileStream);
    FreeAndNil(MemoryStream);
    QueryPerformanceCounter(T2);
    QueryPerformanceFrequency(T3);
    WriteLn(Format('Benötigte Zeit: %.6f s', [(T2-T1)/T3]));
    write('Primzahlen suchen bis (0=Beenden): ');
    readln(MaxPrim);
  end
end.


PS: Komisch, man findet haufen Beiträge zum Thema Primzahloptimierung, aber keins zu einer Primzahlsuche (was richtig ausdiskutiert wurde :mrgreen: )
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Di 10.01.06 19:18 
Hallo,

Wieso dass denn schon wieder ;-)
www.delphi-forum.de/...er=asc&start=220 und folgende
reicht doch voellig.
Wo gezaehlt wird muss ja wohl die Zahl bekannt sein.

Gruss Horst
Heiko Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Di 10.01.06 19:23 
Der Source sieht so lahm*rschig aus, denn mod ist so ziemlich langsam, was ich schon zu meinem Leidwesen feststellen musste ;).

//EDIT: Die schummeln ja. Das Einspeichern von Prims zum Anfang ist ja regelrecht gemein ;).
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Di 10.01.06 22:40 
Mein Primgen findet alle Primzahlen bis 1000359390 in 1720 tics (Pentium M 1.5GHz)
(Sieve of atkins). Kannst gerne die source haben. Sie basieren auf ecprime, einer c-library.
[edit] kurz optimiert, 5% eingespaart [/edit]

_________________
Na denn, dann. Bis dann, denn.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Mi 11.01.06 11:02 
Hallo,

von wegen schummeln.
Bei TurboPascal gibt es nicht soetwas Praktisches wie array of boolean.
Dann haette mein Programm komplett auf die Eingabe von irgendeiner Primzahl verzichten koennen (selbst die 2).
Das ist aber auch egal, mit >Schummeln< ist es eben viel schneller.
Und ausserdem benutzt man ja immer moeglichst viel Erkenntnis und faengt nicht bei der Definition, was ist ueberhaupt eine Zahl und warum das mir , an. ;-)

Gruss Horst
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mi 11.01.06 12:25 
Das 'Schummeln' bringt sowieso nur bei Geschwindigkeitswettbewerben etwas.
Wenn auf die Generierung der ersten 5600 Primzahlen (wie bei PrimeGen) verzichtet wird, und stattdessen ein statisches CONST-Array benutzt wird, macht das performancetechnisch den Kohl nicht fett:
Wenn die Generierung aller Primzahlen bis 1.000.000.000 knapp 1.7 Sekunden dauert, dann kannst Du Dir ja ausrechnen, wie lange die Erstellung des Arrays gedauert hätte. 0.01 Sek? 0.1 Sek?

_________________
Na denn, dann. Bis dann, denn.
Arno-Wien
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 33

xp

BeitragVerfasst: Mi 11.01.06 12:46 
Eine ziemlich schnelle Primzahlspielerei im Anhang
Vielleicht hilft es jemandem
Arno
Einloggen, um Attachments anzusehen!
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Mi 11.01.06 12:58 
Hallo,

ein bessere Beschreibung taete not.
Differenz kleiner als 1000000000 (1e9)ergibt 172 achso????
und eine Menge Primzahlzwillinge ab 1e6
Etwas verwirrend.

Gruss Horst
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mi 11.01.06 13:32 
@Heiko: Dein "Sieb des Eratosthenes" kann noch verbessert werden:
Du suchst die ungeraden Zahlen ab (2,3,5,7). Das ist zuviel. Ohne grossen Aufwand reicht diese Zahlenfolge:
2,3, 5,7 11,13, 17,19 ...

Also neben 2 und 3 nur die Zahlen der Form: 6n +/- 1

_________________
Na denn, dann. Bis dann, denn.