Autor |
Beitrag |
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: 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?  ) 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 (  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)?
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#10, 3); else begin MemoryStream.Write('2'+#13#10, 3); 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)); 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  )
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: 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 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: 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
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: 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
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: 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
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: 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
      
Beiträge: 33
xp
|
Verfasst: Mi 11.01.06 12:46
Eine ziemlich schnelle Primzahlspielerei im Anhang
Vielleicht hilft es jemandem
Arno
Einloggen, um Attachments anzusehen!
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: 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
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: 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.
|
|
|