Autor Beitrag
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Di 23.04.13 21:47 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
würdest du mir allerdings helfen, wie ich eine Datei auf die Festplatte auslagere?

Versuchs mit einem TFileStream. Mit einem TMemoryStream wird es nicht gehen (maximal die schon bekannten 1,5 GB). Ansonsten bliebe noch AssignFile und Co.
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Di 23.04.13 21:49 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
Ansonsten bliebe noch AssignFile und Co.

NEIN! ich caste keine 4 Billionen zahlen in Strings, schreibe sie, und lese/ändere sie dann noch paar mal ! das wären viel zu viele zugriffe.. das würde ca aus vorher 1 sek so ungefähr 1 min machen.. nein danke...
TfileStream ist hoffe ich mal schneller.. werde ich mir später anschauen..

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!


Zuletzt bearbeitet von IhopeonlyReader am Mi 24.04.13 21:24, insgesamt 2-mal bearbeitet
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Di 23.04.13 22:50 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
TfileStream ist hoffe ich mal schneller..
Die Geschwindigkeit hängt davon ab, wie viele Bytes Du auf einen Rutsch liest oder wegschreibst. Je mehr, desto schneller. Einen solchen Block könntest Du z. B. als einen packed record definieren. In diesem gelesenen Block könntest Du dann die Bit-Operationen ausführen. Das spielt sich dann im RAM und nicht auf der Festplatte ab. Ist also bedeutend schneller, als wenn Du jedes einzelne Integer liest und schreibst.
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 24.04.13 16:28 
wie ich schon schrieb, habe ich (4 Mrd +7)er Blöce also 4Mrd +8 Bits = 500000001 Byte-Blöcke = 488281 KB = 476,84 MB = 0,466 GB Blöcke

würdest du bitte ein Beispiel machen?

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Mi 24.04.13 20:44 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
würdest du bitte ein Beispiel machen?

ausblenden 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:
procedure TMainform.Button1Click(Sender: TObject);
var
  Schleife   : cardinal;  // int64 nicht möglich
  ZahlByte   : byte;
  Zahl       : cardinal;
  FS         : TFileStream;
  DatenBlock : array [0..124999of byte; // 125.000 Bytes = 1 Mio. Bits bzw. Zahlen
begin
  FS := TFileStream.Create('L:\Primzahlen.PRIM', fmOpenReadWrite or fmCreate);
  try
    for Schleife := 0 to 124999 do
      DatenBlock[Schleife] := $55;
    for Schleife := 1 to 80000 do   // = 10 Mrd. Bytes große Datei (= 80 Mrd. Bits / Zahlen)
      FS.Write(DatenBlock, SizeOf(DatenBlock));
    FS.Position := 0;                    // zurück zum Anfang
    FS.Read(ZahlByte, SizeOf(ZahlByte)); // nur ein Byte lesen
    ZahlByte := ZahlByte xor $03;        // 1 keine Primzahl, 2 = Primzahl
    FS.Position := 0;         // Durch das Lesen wurde der Zeiger verschoben.
    FS.Write(ZahlByte, SizeOf(ZahlByte));
      // Kleiner Test, um das Endian-Problem zu verdeutlichen.
    FS.Position := 10;        // Durch das Schreiben wurde der Zeiger verschoben.
                              // Wird hier willkürlich auf 10 (= 11. Byte) gesetzt.
    Zahl := $12345678;        // Im Hex-Editor mal die Bytes ansehen. (siehe Endian)
    FS.Write(Zahl, SizeOf(Zahl));
  finally
    FS.Free;
  end;
end;


Ein paar Anmerkungen dazu.

1. Durch das Endian-Format wird die Bytefolge $12345678 als 78 56 34 12 in der Datei abgelegt.
2. Liest man einen Integer und rechnet "Integerwert xor 3", dann wird das höherwertigste Byte (ganz links) geändert und nicht das niederwertigste, was man ja erwarten würde. Deshalb lese und schreibe ich hier nur Bytes, keine Integer.
3. Durch ein Lesen oder Schreiben im FileStream wird der Positionszeiger erhöht. Deshalb vorher FileStream.Position setzen.
4. Beim Testen erst einmal mit kleineren Dateigrößen anfangen. Bei einem Testlauf habe ich eine 40 GB große Datei erzeugen können. Größer ging hier nicht, weil nicht genügend Platz auf der Partition war.
5. Da die Anwendung durch das Bearbeiten des großen Streams blockiert wird, empfiehlt es sich, das in einen Thread auszulagern.
6. Der Datenblock kann nicht beliebig vergrößert werden, sonst gibt es Probleme mit dem Heap.
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mi 24.04.13 21:21 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:

var
Schleife : cardinal; // int64 nicht möglich

doch wenn du dein
ausblenden Delphi-Quelltext
1:
2:
3:
4:
For Schleife:=1 to 80000 do
 begin
 //
 end;

gegen
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
Schleife := 1;
while Schleife <= 80000 do
 begin
 //
 inc(Schleife);
 end;

tauscht..
aber danke für dein Beispiel :), weißt du wie lange das ca dauert, bis 0,5 Gb geschrieben/gelesen sind?
weil wenn ich das in ein extra thread packe, und der dann mit der Berechnung schneller ist, als mit dem schreiben.. naja dann liest er wo noch nicht geschrieben ist!

deshalb ist das mit dem extra thread, naja ich sag mal "Festplattenabhängig"..

ich hatte vor, 1 Block IMMER im Arbeitsspeicher behalten (geht von Zahl 1 bis 8 Mrd), da hier die Zahlen sind, deren vielfaches gestrichen wird... die blöcke in denen gestrichen wird, würde ich dann "hin und her" schieben.. wahrscheinlich würde ich sogar ERST den kompletten 2ten block berechnen, block 2 auf Festplatte schieben, block 3 rausholen, kompletten block 3 machen, block 3 auf Festplatte schieben, block 4 holen....
Ich denke das sollte klappen :) Dann wären Berechnungen bis (8Mrd)² möglich! (die vorherigen (4Mrd)² wurden verdoppelt, da ich nur noch ungerade zahlen in dem bit-boolean Array habe !

Nachtrag 1: oder glaubst du der liest/schreibt schnell genung, dass ich direkt das vielfache von PrimX bis zum letzten Block "in einem Wisch" ausstreichen kann?

Nachtrag : Nach genauerem Anschauen deines Code verstehe ich eine Zeile nicht:
ausblenden Delphi-Quelltext
1:
for Schleife := 1 to 80000 do   // = 10 Mrd. Bytes große Datei (= 80 Mrd. Bits / Zahlen)					

klar, das ist die Schleife in der du den DatenBlock auf die Festplatte (in den Stream) schreibst, aber warum nur bis 80000?
ebenso verstehe ich den sinn von deiner Variable ZahlByte nicht...

P.S:
ausblenden Delphi-Quelltext
1:
 DatenBlock[Schleife] := $55;					

würde jede gerade zahl auf true setzten^^ (vorrausgesetzt man beginnt mit 1 (der ersten natürlichen positiven zahl, die also in der lage sei eine Primzahl zu sein)

Nachtrag 3 (solangsam sollte ich erst alle fragen überlegen :D): Ich würde gerne in die 1 "Zeile" bzw. an anfang die Größe des Arrays schreiben!, da der letzte block nicht immer aus 4 Mrd Bits besteht (bei der Berechnung bis 20 Mrd bestehen Block 1 und 2 aus je 4Mrd und Block 3 aus 2 Mrd Bits)...
und da ich ja mehrere blöcke nach "hinten" versetzte, sollte ich dann ein Array of TFileStream anlegen?
und auslesen geht mit (wenn ich die Arraylänge aus der ersten zeile bereits kenne womit? .. bitte schreibe mir die "schreib" und "lese" schleifen einmal als Beispiel :)...

ich denke es muss
ausblenden Delphi-Quelltext
1:
2:
For Schleife:=1 to High(DatenBlock) do
 FS.WriteBuffer(DatenBlock[Schleife], SizeOf(DatenBlock[Schleife]); //WriteBuffer oder Write?
sein... und mir ist eingefallen, ich könnte die "größe des Arrays" ja auch als Int64 Zahl zusammen mit dem Pfad einfach abspeichern, dann muss dass nicht mit in die Datei rein..
lesen geht mit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
{Type TSavedDataBlocks = record
 Pfad: String; //fester Pfad + '\' + IntToStr(BlockNr);
 Anzahl: Cardinal
end;
var GespBloecke: Array of TSavedDataBlocks;}


setlength(DatenBlock, Gesp[BlockNr].Anzahl);
For Schleife:=High(DatenBlock) downto 1 do // von hinten nach vorn, wie du oben sagtest ist richtig oder?
  FS.ReadBuffer(DatenBlock[Schleife], SizeOf(DatenBlock[Schleife])); //ReadBuffer oder Read ? ich kenns mit Buffer...

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Do 25.04.13 01:00 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
weißt du wie lange das ca dauert, bis 0,5 Gb geschrieben/gelesen sind?

40 GB in etwa 8 Minuten inklusive der Initialisierung. Das Schreiben und Lesen geht wirklich sehr schnell, nur das Initialisieren des Datenblocks dauert etwas. Das hängt aber von der Größe ab. Da kannst Du bei der Größe ruhig etwas experimentieren.

Zitat:
weil wenn ich das in ein extra thread packe, und der dann mit der Berechnung schneller ist, als mit dem schreiben.. naja dann liest er wo noch nicht geschrieben ist!

Ich meinte alles in einen Thread auslagern. Also beginnend ab FileStream.Create, dem Initialisieren des Datenblocks, das Schreiben der Datenblocks bis zur gewünschten Dateigröße, das Sieben usw.


Zitat:
ich hatte vor, 1 Block IMMER im Arbeitsspeicher behalten (geht von Zahl 1 bis 8 Mrd), da hier die Zahlen sind, deren vielfaches gestrichen wird... die blöcke in denen gestrichen wird, würde ich dann "hin und her" schieben.. wahrscheinlich würde ich sogar ERST den kompletten 2ten block berechnen, block 2 auf Festplatte schieben, block 3 rausholen, kompletten block 3 machen, block 3 auf Festplatte schieben, block 4 holen....
Ich denke das sollte klappen :) Dann wären Berechnungen bis (8Mrd)² möglich! (die vorherigen (4Mrd)² wurden verdoppelt, da ich nur noch ungerade zahlen in dem bit-boolean Array habe !


Zitat:
klar, das ist die Schleife in der du den DatenBlock auf die Festplatte (in den Stream) schreibst, aber warum nur bis 80000?
ebenso verstehe ich den sinn von deiner Variable ZahlByte nicht...

Ich habe einfach diesen Wert genommen, um beim Testen nicht jedes Mal minutenlang warten zu müssen. Einfach den Wert erhöhen, und Du hast eine größere Datei. ZahlByte ist einfach der Name für eine Byte-Variable. Wegen der Endian-Speicherung würde ich Dir dringend empfehlen, hier mit Bytes zu arbeiten, sonst schaffst Du Dir hier unnötig Probleme. Siehe im Beispiel "Zahl := $12345678;". Da schreibe ich eine Zahl (= 4 Bytes).

Zitat:

ausblenden Delphi-Quelltext
1:
 DatenBlock[Schleife] := $55;					

würde jede gerade zahl auf true setzten^^ (vorrausgesetzt man beginnt mit 1 (der ersten natürlichen positiven zahl, die also in der lage sei eine Primzahl zu sein)

Nein. Lese mal die Bits von rechts nach links. Mit $55 werden alle Bits gesetzt (01 01 01 01), die den ungeraden Zahlen entsprechen sollen. Zum Schluss schieße ich im ersten Byte der Datei die Bits um, weil 1 keine Primzahl ist, 2 aber doch. Dann steht dort $56 (01 01 01 10). Immer daran denken, es wird von rechts nach links gelesen.

Um es noch einmal zu verdeutlichen, wie das funktionieren soll:

Jedes Byte repräsentiert 8 Zahlen. Im ersten Byte stehen die Bits (immer von rechts nach links lesen) für die Zahlen 8 7 6 5 4 3 2 1.
Für die z. B. ersten drei Bytes stehen die Bits für folgende Zahlen: 8 7 6 5 4 3 2 1 *** 16 15 14 13 12 11 10 9 *** 24 23 22 21 20 19 18 17.

Zitat:
Ich würde gerne in die 1 "Zeile" bzw. an anfang die Größe des Arrays schreiben!, da der letzte block nicht immer aus 4 Mrd Bits besteht (bei der Berechnung bis 20 Mrd bestehen Block 1 und 2 aus je 4Mrd und Block 3 aus 2 Mrd Bits)...

Wozu? Du kennst die Dateigröße bzw. kannst die abfragen. Da jedes Byte 8 Zahlen entspricht, kennst Du auch den Maximalwert dafür.

Zitat:
und da ich ja mehrere blöcke nach "hinten" versetzte, sollte ich dann ein Array of TFileStream anlegen?

TFileStream ist eine nicht visuelle Komponente zum Schreiben und Lesen von Dateien. Wenn Du vier Leute nacheinander anrufen möchtest, schaffst Du Dir ja auch nicht extra dafür vier Telefone an. :-)


Zitat:
und auslesen geht mit (wenn ich die Arraylänge aus der ersten zeile bereits kenne womit? .. bitte schreibe mir die "schreib" und "lese" schleifen einmal als Beispiel :)...

ich denke es muss
ausblenden Delphi-Quelltext
1:
2:
For Schleife:=1 to High(DatenBlock) do
 FS.WriteBuffer(DatenBlock[Schleife], SizeOf(DatenBlock[Schleife]); //WriteBuffer oder Write?
sein... und mir ist eingefallen, ich könnte die "größe des Arrays" ja auch als Int64 Zahl zusammen mit dem Pfad einfach abspeichern, dann muss dass nicht mit in die Datei rein..

lesen geht mit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
{Type TSavedDataBlocks = record
 Pfad: String; //fester Pfad + '\' + IntToStr(BlockNr);
 Anzahl: Cardinal
end; 
var GespBloecke: Array of TSavedDataBlocks;}

Wozu???

Zitat:
ausblenden Delphi-Quelltext
1:
2:
3:
setlength(DatenBlock, Gesp[BlockNr].Anzahl);
For Schleife:=High(DatenBlock) downto 1 do // von hinten nach vorn, wie du oben sagtest ist richtig oder?
  FS.ReadBuffer(DatenBlock[Schleife], SizeOf(DatenBlock[Schleife])); //ReadBuffer oder Read ? ich kenns mit Buffer...

In meinem Beispiel verwende ich kein ReadBuffer und auch kein WriteBuffer. Gelesen wird, in dem man FileStream.Position auf das Byte vor den zu lesenden oder zu schreibenden Bereich setzt und dann mit FileStream.Write bzw. Read den Bereich schreibt oder liest. Man kann ein einzelnes Byte ansprechen (siehe ZahlByte im Beispiel), ein Word, ein Integer, ein Int64, ein Array of irgendwas oder sonst was lesen und schreiben. ABER: Das Sieb des Erastothenes funktioniert hier nur, wenn die Bits geordnet in der Datei vorliegen. Mit Integer oder Int64 auf das Datenmaterial in der Datei zuzugreifen ist tödlich, weil beim Speichern die Bytereihenfolge auf der Festplatte geändert wird (siehe: de.wikipedia.org/wiki/Byte-Reihenfolge). Aus $12345678 wird dann ein $78563412 auf der Platte. Führe mein Beispiel mal unverändert aus und schaue Dir dann die Datei im Hex-Editor an. Greift man dann auf die Daten mit Read(ZahlByte, SizeOf(ZahlByte)) zu, handelst Du Dir falsche Werte bei der nachfolgenden Bearbeitung ein. Ein "$55 xor $03" macht mit den Daten etwas anderes als ein "$55555555 xor $03". Teste es aus!
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 378
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: Do 25.04.13 20:15 
Vielleicht liest es ja noch jemand:

Zumindest wenn das RAM voll ist und die Auslagerungsdatei gebraucht wird, dann ist auch Kompression eine Option. Kompression/Dekrompession kann viel schneller sein als I/O von der Festplatte.

Leider hängt es von der Datenart und der Abstimmung zwischen Kompressionverfahren und Datenart ab, was man gewinnt (und ob überhaupt). Zum Vergleich: ZIP reduziert die Größe der meisten üblichen Dateitypen ganz grob geschätzt um den Faktor 2, bei einigen Dateitypen bringt es praktisch nichts, gelegentlich bringt es auch dramatisch mehr. (Test mit einem Zipper: 1 MB mit Nullen wird auf ca. 1 kB komprimiert, 1 MB mit Zufallszahlen wird sogar um wenige Bytes größer. Kein überraschendes Ergebnis, zeigt aber schön den Effekt).

Ich würde damit anfangen, einen Testdatensatz zu zippen, das gibt schon ein Indiz. Evtl. es auch einmal mit anderen Kompressionverfahren zu versuchen.
Wenn da keine Kompression erreicht werden kann, dann würde ich dann Ansatz vergessen, auch wenn theoretisch was möglich wäre.

Gruß
GuaAck
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: So 28.04.13 14:30 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:

Zitat:
und da ich ja mehrere blöcke nach "hinten" versetzte, sollte ich dann ein Array of TFileStream anlegen?

TFileStream ist eine nicht visuelle Komponente zum Schreiben und Lesen von Dateien. Wenn Du vier Leute nacheinander anrufen möchtest, schaffst Du Dir ja auch nicht extra dafür vier Telefone an. :-)
habe ich beachtet :) es gibt nun ein "speicher" und Lade- "thread"... denn wenn er z.B. mit block 3 fertig ist, muss 3 ja nach hinten geschoben werden und block 5 schonmal geladen werden... dann rechnet wer mit block 4, danach schiebt er block 4 nach hinten und holt 6 schomal hervor ...

user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:

In meinem Beispiel verwende ich kein ReadBuffer und auch kein WriteBuffer. Gelesen wird, in dem man FileStream.Position auf das Byte vor den zu lesenden oder zu schreibenden Bereich setzt und dann mit FileStream.Write bzw. Read den Bereich schreibt oder liest. Man kann ein einzelnes Byte ansprechen (siehe ZahlByte im Beispiel), ein Word, ein Integer, ein Int64, ein Array of irgendwas oder sonst was lesen und schreiben. ABER: Das Sieb des Erastothenes funktioniert hier nur, wenn die Bits geordnet in der Datei vorliegen. Mit Integer oder Int64 auf das Datenmaterial in der Datei zuzugreifen ist tödlich, weil beim Speichern die Bytereihenfolge auf der Festplatte geändert wird (siehe: de.wikipedia.org/wiki/Byte-Reihenfolge). Aus $12345678 wird dann ein $78563412 auf der Platte. Führe mein Beispiel mal unverändert aus und schaue Dir dann die Datei im Hex-Editor an. Greift man dann auf die Daten mit Read(ZahlByte, SizeOf(ZahlByte)) zu, handelst Du Dir falsche Werte bei der nachfolgenden Bearbeitung ein. Ein "$55 xor $03" macht mit den Daten etwas anderes als ein "$55555555 xor $03". Teste es aus!


ok, ich "benutzte" zwar Bit-Booleans, aber zur Auslagerung lagere ich die Bytes (mit je 8 Bit-Booleans) aus.. ich denke das ist schneller, daher ist es mit BUFFER dann doch richtig oder?.. ich wird mal beides ausprobieren


user profile iconGuaAck hat folgendes geschrieben Zum zitierten Posting springen:
Vielleicht liest es ja noch jemand:

Ja^^
user profile iconGuaAck hat folgendes geschrieben Zum zitierten Posting springen:

Zumindest wenn das RAM voll ist und die Auslagerungsdatei gebraucht wird, dann ist auch Kompression eine Option. Kompression/Dekrompession kann viel schneller sein als I/O von der Festplatte.

naja, zumindest beim "ersten" auslagern wird dies sicherlich SEHR nützlich sein, da hier ja alle noch auf True (1) sind..

Allerdings: ich denke ich werde es zwar auslagern, aber die "späteren" Blöcke nicht auslagern, sondern erst später erstellen..

Bsp. während Block 1 Berechnet wird, wird Block 2 erstellt.
Danach wird Block 1 gespeichert (aber nicht freigeben, da hierraus die vielfachen ja noch gestrichen werden), block 2 wird "errechnet" und block 3 wird erstellt..
Danach wird Block 2 ausgelagert, block 3 berechnet und block 4 erstellt...

Nachtrag:
Zitat:
Wozu? Du kennst die Dateigröße bzw. kannst die abfragen. Da jedes Byte 8 Zahlen entspricht, kennst Du auch den Maximalwert dafür.

Nicht ganz, es gibt eine "Mindestgröße" für eine Datei (zumindest bei Windows).. wenn ich Primzahlen bis 4Mrd + 10 berechne, dann ist die 2teAuslagerungsdatei > 10 Bits!
ich glaube unter Windows kann man die "Mindestgröße" im Bereich "schnell"/"speichernutzung" der Festplatte einstellen.. sie beträgt zwischen 104 B und 4096 B/ 4KB soviel ich weiß.. daher ist dies nicht immer möglich (meine Mindestgröße liegt bei 1 KB)

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: So 28.04.13 16:58 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Nicht ganz, es gibt eine "Mindestgröße" für eine Datei (zumindest bei Windows).. wenn ich Primzahlen bis 4Mrd + 10 berechne, dann ist die 2teAuslagerungsdatei > 10 Bits!
ich glaube unter Windows kann man die "Mindestgröße" im Bereich "schnell"/"speichernutzung" der Festplatte einstellen.. sie beträgt zwischen 104 B und 4096 B/ 4KB soviel ich weiß.. daher ist dies nicht immer möglich (meine Mindestgröße liegt bei 1 KB)

Da verwechselst Du was. Die Dateigröße und die Größe des belegten Festplattenspeichers sind zwei Paar Schuhe. Was der Windowsexplorer anzeigt, ist wieder etwas anderes.

Die Dateigröße (die man abfragen kann) gibt die Byte-genaue Größe der Datei an. Der belegte Festplattenspeicher ist etwas größer, weil für eine Datei größer 0 Bytes immer mindestens ein ganzer Cluster (besteht aus mehreren Sektoren) belegt wird. Und der Windowsexplorer kennt nur 0 Bytes oder mindestens 1 KB.
Einloggen, um Attachments anzusehen!
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mo 29.04.13 20:51 
ok stimmt natürlich Gerd...
ich habe mir überlegt, dass es ja sinnlos wäre die fertig initialisierten Bits, die am Anfang noch 1 (True) sind, auszulagern.. dafür, wie das gehen wird, danke ich dir noch einmal user profile iconGerd Kayser . ich werde aus "übungsgründen" später noch einmal mit "Auslagerung" umsetzen.

Jetzt erstelle ich die Blöcke erst, wenn sie benötigt werden, nach der Berechnung werden sie gespeichert und danach gelöscht...

zur Zeit berechne ich die Primzahlen bis 100 Mrd.. mal schauen wie lange er ca. pro block braucht

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Mr_Emre_D
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 114
Erhaltene Danke: 14



BeitragVerfasst: Mi 08.05.13 22:08 
Mal ne Frage - ging es hier eig. ausschließlich darum, Boolean Arrays kleiner zu kriegen oder eher darum, möglichst viele / große Primzahlen zu berechnen (mit Delphi-Hausmitteln)?

Falls es ums zweitere ging:
Man benötigt kein großes Array, es reicht vollkommen ein z.B. 1024 Byte großes Array herzunehmen.
Man fängt wie gewohnt bei 1 an, wendet den Siebalgo an und hat einmal alle Primzahlen von 1..1024 ermittelt.
Als nächstes verschiebt man das Array um +1024; die Dimension des Arrays ändert sich nicht, jedoch ist Array[0] = die Zahl 1024!
Dh. man wendet den Siebalgo nochmal an - natürlich rechnet man jz nicht per Addition hoch bis man bei 1024 angelangt ist,
sondern macht einfach eine Division, rundet ab und multipliziert dann mit dem Faktor und schon ist man direkt vor 1024.
Dann wie gewohnt addieren und Vielfache eleminieren. Natürlich index anpassen (-1024 rechnen).
Somit kann man Stück für Stück immer 1024 (meinetwegen auch mehr) berechnen.
Die Grenze ist dann für Delphi Int64 (2^64)

Das ganze dürfte dann natürlich dauern!
Demo folgt sofern mir die Lust nicht vergeht!

Edit: Der Nachteil ist jedoch, dass man trotzdem jedesmal wieder die Vielfachen von Anfang an eleminieren muss.
Dafür ist man halt das Problem mit dem Speicher los. Man muss halt abwägen..


Zuletzt bearbeitet von Mr_Emre_D am Mi 08.05.13 23:46, insgesamt 1-mal bearbeitet
Mr_Emre_D
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 114
Erhaltene Danke: 14



BeitragVerfasst: Mi 08.05.13 23:39 
Habs grad implementiert und direkt getestet.
Als ByteBooleanArray Größe habe ich 1 mb genommen (1024 * 1024). Dh ich berechne zuerst die Primzahlen
[3, 1024*1024], dann
[3 + 1024*1024, 3 + 1024*1024*2], anschließend
[3 + 1024*1024*2, 3 + 1024*1024*3] usw usf.

Allgemein
[3 + 1024*1024*x, 3 + 1024*1024*(x+1)]

Habe grad bis 4096 iteriert (das sind dann 4096 * 1024*1024 = 4 gb).
Auf meinem Rechner hat es 218.92 Sekunden gedauert und eine Blockberechnung (1mb) hat im Schnitt 55 Ticks gedauert.
Auf die Ausgabe habe ich verzichtet, wer mag, kann es ausgeben lassen bzw. den Code so ändern, dass die Ausgabe gespeichert wird.

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:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
program LOP;

// Lots Of Primes
// mr_emre_d
// @ entwickler-ecke.de

{$APPTYPE CONSOLE}

uses
  Windows;

type
  TByteBoolean = record
    Value: Byte;
    function GetBit(const Index: Integer): Boolean;
    procedure SetBit(const Index: Integer; const Bit: Boolean);
  end;

  TByteBooleanArray = Array of TByteBoolean;

{$REGION 'TByteBoolean'}

function TByteBoolean.GetBit(const Index: Integer): Boolean;
begin
  Result := Value and (1 shl Index) <> 0;
end;

procedure TByteBoolean.SetBit(const Index: Integer; const Bit: Boolean);
begin
  if Bit then
    Value := Value or (1 shl Index)
  else
    Value := Value and not (1 shl Index);
end;

{$ENDREGION}

(*
** ExtendedSieveOfEratosthenes calculates primenumber in a given range
** the range is specified by [StartingNumber, Primes.Len*2]
** Primes.Len * 2 because the Primes Array only contains odd numbers (since even numbers cant be prime)
*)

procedure ExtendedSieveOfEratosthenes(const FromOffset: UInt64; var Primes: TByteBooleanArray);
var
  ToOffset  : UInt64;
  candidate : UInt64;
  multiples : UInt64;
  index     : Integer;
begin
  candidate := 3;
  ToOffset := FromOffset + Length(Primes) shl 4;
  while candidate < ToOffset do
  begin
    // fast-iterate to the beginning of the sieve
    if candidate < FromOffset then
    begin
      multiples := candidate * Round(FromOffset/candidate);
      if multiples < FromOffset then
        inc(multiples, candidate);
    end else
      multiples := candidate shl 1;

    // if the first multiple is already out of bounds we can stop sieving
    if multiples > ToOffset then break;

    // sieve
    while multiples <= ToOffset do
    begin
      // odd numbers only
      if multiples and 1 = 1 then
      begin
        index := (multiples - FromOffset) shr 1;
        Primes[index shr 3].SetBit(index mod 8, false);
      end;
      inc(multiples, candidate);
    end;

    // ignore even numbers
    inc(candidate, 2);
  end;
end;

var
  Primes: TByteBooleanArray;
  iteration: Integer;
  p, q: Integer;
  From: UInt64;
  Tick: DWORD;
  Duration: DWORD;
  Til: UInt64;
  PrimeCount: UInt64;
  ptr: PDWord;
  cnt4: DWord;

begin
  SetLength(Primes, 1024*1024 shr 4);
  From := 3;
  Til := 1000000000;
  Til := Til * 12;
  iteration := 0;
  PrimeCount := 0;
  Duration := GetTickCount;
  cnt4 := Length(Primes) div 4;
  while From < Til do
  begin
    inc(iteration);
    ptr := @Primes[0];
    for p := 0 to cnt4 do
    begin
      ptr^ := $FFFFFFFF;
      inc(ptr);
    end;
    ExtendedSieveOfEratosthenes(From, Primes);
    for p := 0 to High(Primes) do
      for q := 0 to 7 do
        if Primes[p].GetBit(q) then
        begin
          if (From + (p*8 + q)*2) < Til then
            inc(PrimeCount);
//          Writeln(PrimeCount, '. ', (From + (p*8+q)*2));
        end;
//    Readln;
    if iteration mod 100 = 0 then
      Write('[Iteration #', iteration, '] calculated primes [', From, ', ', From + Length(Primes) shl 1,
        '] (time: ', (GetTickCount-Duration)/1000:6:2')'#13);
    inc(From, Length(Primes) shl 4);
  end;
  Duration := GetTickCount - Duration;

  Writeln('Finished, took me ', Duration/1000:8:2' seconds... ');
  Writeln('Found ', PrimeCount, ' primes');
  Readln;
end.


Zuletzt bearbeitet von Mr_Emre_D am Do 09.05.13 03:13, insgesamt 6-mal bearbeitet
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1448

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mi 08.05.13 23:48 
Hallo,
user profile iconMr_Emre_D hat folgendes geschrieben Zum zitierten Posting springen:
Habe grad bis 4096 iteriert (das sind dann 4096 * 1024*1024 = 4 gb).
Auf meinem Rechner hat es 218.92 Sekunden gedauert und eine Blockberechnung (1mb) hat im Schnitt 55 Ticks gedauert.

Ich will Dich ja nicht ärgern, aber Dein Verfahren hat user profile iconHorst_H schon in mehreren Threads zu Primzahlen beschrieben.
Bei meiner Suche nach einsamen Primzahlen www.entwickler-ecke....ewtopic.php?t=111471 dauert das Sieben (+ Auswertung und die kostet Zeit) von 4 Milliarden Primzahlen auf meinem alten PC nur 28 Sekunden.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Mr_Emre_D
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 114
Erhaltene Danke: 14



BeitragVerfasst: Mi 08.05.13 23:51 
Das ärgert mich nicht.
Wie bereits zuvor schon geschrieben, war mir klar, dass diese Variante nicht schnell(er) ist, dafür hat sie aber das Problem mit dem Speicher nicht.
Und darum ging es hier doch, bei diesem Thread, nicht?
Mr_Emre_D
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 114
Erhaltene Danke: 14



BeitragVerfasst: Do 09.05.13 01:59 
[doppelpost]
IhopeonlyReader Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Do 09.05.13 13:56 
hättest du den ganzen Thread mitverfolgt, wüsstest du dass ich das bereits mache ;)
ich berechne 1 block (bei mir ist 1 block 4 mrd booleans groß) und danach den nächsten und so weiter....
ich brauche für Primzahlen bis 4 Mrd ca 120 sek und mein Programm ist (wenn es voll rechnet, also 3x 4mrd booleans im speicher hat (1x unterste4n Primzahlen deren vielfaches in block X weggestrichen werden und der fertige block der abgespeichert wird) kleiner als 1 GB (928 MB) im Arbeitsspeicher (ram)

berechne ich ohne "arbeitsspeicherplatzsparung" schaffe ich die zahlen bis 4 mrd leider nicht, da Delphi nur bis 1,5 gb ram nutzen kann.. bis 1 mrd brauch ich ohne sparung 15 sek

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Mr_Emre_D
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 114
Erhaltene Danke: 14



BeitragVerfasst: Do 09.05.13 15:24 
Ich bin eigentlich über den ganzen Thread drübergeflogen (hab mir halt nur die Sourcen nicht angescahut)..
Falls dir das eh eingefallen ist, nvm!
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Do 09.05.13 20:51 
Zur Auslagerung auf die HDD sollte man evtl. MMF's verwenden.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Fr 10.05.13 11:38 
Hallo,

was will man mit den ganzen Zahlen auf der Festplatte?
Kleinere Abschnitte zu Bearbeiten ist von großem Vorteil, es geht einfach viel schneller, weil der Speicherzugriff beim Sieben über große Distanzen erfolgt und damit langsam ist.
120 Sekunden für 4 Milliarden ist nicht überaus schnell.
SegSiebTest.pas benötigt bei mir ca 10 Sekunden und kann bis 2.6e11 Sieben.Die unit mp_prime ist von user profile iconGammatester aus mparith.
Diese habe ich nur aus Bequemlichkeit drin.Natürlich kann ich mit dem eigenen Sieb selbst die Zahlen ersieben.

Viel Interessanter wäre doch, von Kim Walisch die C++ object Datei einbinden zu können-> Die Summe der ersten 1e9 Primzahlen ( bis 22.801.929.150 zu sieben ) in 10 Sekunden.
Mein Programm braucht schon über 60 Sekunden für das sieben ( Ok: Addieren geht fast unbemerkt unter ) und circa 5.7 Mb Platz, davon 5 Mb für die Primzahlen.
ausblenden Quelltext
1:
2:
3:
4:
Hoechste Primzahl 510529
Siebe ab                  0
Gesiebt bis     22801929150      1.000.006.971
real  1m1.053s

Es siebt und zählt immer vollständige Siebe a 510510 Elemente, deshalb sind es 6.971 mehr.
Es lohnt sich nicht, die Festplatte zu quälen ;-)

Gruß Horst

Für diesen Beitrag haben gedankt: Mathematiker