Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Lesegeschwindigkeit von Platte

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 43

BeitragVerfasst am: 07.07.2020, 12:45    Titel: Lesegeschwindigkeit von Platte Antworten mit Zitat

Hallo, ich wollte gerne einmal nachfragen, wie hoch Eurer Datensatz / s ist.
Worum gehts....ich arbeite mit sehr großen Datein , die viele Zahlen enthalten.
Ich rede hier von 5GB Datein mit ca. 230 Mio Zeilen.
Der PC (Ryzen,Win10) schafft ca. 700000 Zeilen pro Sekunde. (~10 MB/s)
Die Zahl wird zeilenweise gelesen und gleich verarbeitet...nächste Zahl gelsen usw

Sprache: Freebasic, Platte: HDD

Kann man diese Rate steigern oder ist dies normal ?

Gruß
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
dreael
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 2485
Wohnort: Hofen SH (Schweiz)

BeitragVerfasst am: 07.07.2020, 19:18    Titel: Antworten mit Zitat

Einfache Antwort: Auf SSD wechseln, falls aktuell noch eine mechanische Festplatte dreht!

Primär beschleunigt eine SSD Lesezugriffe, speziell, wenn diese nicht sequenziell erfolgen, sondern viel Random Access. In FreeBasic: Wenn viel mit SEEK in grossen Dateien herumgesprungen wird, wo dann eine mechanische Festplatte nur noch viel am Rattern ist.

Natürlich auch wichtig: Grösse des RAM (Arbeitsspeicher); bei üppig ausgestattetem Rechner kann es passieren, dass es nur das erste Mal länger geht und beim zweiten Mal viel schneller, weil alles im RAM gecacht ist: Situation einer In-Memory-Datenbank.
_________________
Teste die PC-Sicherheit mit www.sec-check.net
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1051
Wohnort: Ruhrpott

BeitragVerfasst am: 07.07.2020, 23:46    Titel: Antworten mit Zitat

Das zeilenweise Nachladen von Daten kostet relativ viel Zeit. Schneller ist es, die Daten in größeren Blöcken von der Festpaltte zu holen. Das erfordert dann allerdings einen geeigneten Parser, der auch das rechtzeitige Nachladen übernimmt.

Code:
Dim As String block
Dim As Integer blocklaenge = 2^20 'Blockgröße 1MB

Open "C:\datei.dat" For Binary Access Read As #1

Do
   block += Input(blocklaenge, #1) 'nächsten Datenblock nachladen
   '
   'Daten parsen und verarbeiten
   '
   '
Loop Until Eof(1)
Close 1


Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
St_W



Anmeldungsdatum: 22.07.2007
Beiträge: 940
Wohnort: Austria

BeitragVerfasst am: 08.07.2020, 20:43    Titel: Antworten mit Zitat

Ich hatte mal vor einigen Jahren eine kleine Filestream Klasse geschrieben für meine damaligen Bedürfnisse. Unterstützt aber wirklich nur das notwendigste, sprich einzelne/mehrere Bytes aus einer Datei zu lesen. Funktionen zum Lesen von Zeilen oder peek() Funktionalität ist da nicht dabei. Vielleicht dennoch ein guter Start oder zumindest ein Denkanstoß lächeln
Code:
'
' File Stream
' version 0.1 (2011)

Type FileStream
   
   Public:
   
   FileName As String
   
   Declare Function ReadData(Buffer As ZString Ptr, MaxLen As UInteger) As UInteger
   Declare Function ReadByte() As UByte
   Declare Function atEOF() As Integer
   Declare Sub CloseStream()
   
   Declare Property Position() As UInteger
   Declare Property Length() As UInteger
   
   Declare Constructor(FileName As String)
   Declare Destructor()
   
   Private:
   
   Declare Sub fillBuffer(filePos As UInteger)
   
   Const bufLen As Integer = 1024*4
   fileBuf As String * (bufLen+1)
   filePos As UInteger = 0
   fileLength As UInteger = 0
   fileNo As UInteger = FreeFile()
   bufPos As UInteger = 0
   isOpen As Integer = -1
   
End Type

Property FileStream.Position() As UInteger
   Return this.filePos
End Property

Property FileStream.Length() As UInteger
   Return this.fileLength
End Property

Constructor FileStream (FileName As String)
  this.FileName = FileName
  Open FileName For Binary As #this.fileNo
  fileLength = Lof(fileNo)
End Constructor

Destructor FileStream ()
   this.CloseStream()
End Destructor

Function FileStream.ReadByte() As UByte
   If fileLength = 0 Then Return 0
   If atEOF Then Return 0
   If bufPos = 0 Or filePos >= bufPos+bufLen Then fillBuffer(filePos+1)
   filePos += 1
   Return fileBuf[filePos-bufPos]
End Function

Function FileStream.ReadData(Buffer As ZString Ptr, MaxLen As UInteger) As UInteger
   Dim cntBytes As UInteger = 0
   For q As UInteger = 0 To MaxLen-1
      If atEOF Then Exit For
      Buffer[q] = this.ReadByte()
      cntBytes += 1
   Next
   Return cntBytes
End Function



Function FileStream.atEOF() As Integer
   Return filePos = fileLength
End Function

Sub FileStream.CloseStream()
   If isOpen then
     Close #this.fileNo
     fileLength = 0
     filePos = 0
     this.isOpen = 0
   End If
End Sub

Private Sub FileStream.fillBuffer(filePos As UInteger)
   Get #fileNo,filePos,fileBuf
   bufPos = filePos
End Sub

_________________
Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken)
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 43

BeitragVerfasst am: 09.07.2020, 19:06    Titel: Antworten mit Zitat

Danke für die Antworten, werde mir das mit den blockweise einlesen mal anschauen.

SSD ist dasselbe bzl Speed

Problem was ich hier habe, dass ich die Zahlen zeilenweise verarbeiten muss und sofort wieder verworfen werden. Anstatt bei 8 Tasks gleichzeitig alles in den RAM zu laden, wird einmalig von der Platte gelesen.

Vielleicht liegt es an Freebasic ?

Mein Kumpel hat auf einem i9 auf Wunsch alle Zahlen bis 100Mio auf Platte geschrieben. Das zeilenweise Einlesen hat bei ihm 8s gedauert. Sprache: C++
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 43

BeitragVerfasst am: 09.07.2020, 23:32    Titel: Antworten mit Zitat

Ich habe den Rat von grindstone befolgt.


Open "E:\TUPEL\3TEX777.bin" for Binary Access Read As #1

PRINT timer
WHILE NOT EOF(1)
S=Input(20000000, #1)
FOR v=1 TO 20000000 STEP 20
M1=VAL(MID(S,v,10))
M2=VAL(MID(S,v+10,10))
REM PRINT M1,M2:SLEEP
NEXT v
WEND

print timer
CLOSE #1

Keine Frage, für große Blöcke, liest er schnell die Datei aus, wenn ich aber
aus dem langen String die nummerischen Werte (auf 10 Stellen formatiert)
zurückgewinne, ist es wieder sehr langsam. ( 1mio/s )
Offenbar verliert Freebasic beim verarbeiten oder umrechnen in Integerwerte aus Strings viel Zeit oder gibt es noch andere Dinge ?

Ob aus einem 100 MB String die Zahlen zu gewinnen ist in etwa gleich , wie zeilenweise Integer gleich einzulesen.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4372
Wohnort: ~/

BeitragVerfasst am: 10.07.2020, 13:17    Titel: Antworten mit Zitat

MID ist nicht gerade das Schnellste (weil automatische Sicherheitsprüfungen durchgeführt werden, ob die Angaben im erlaubten Intervall liegen; und es ist sicher auch nicht so günstig, dass der Start der nächsten Zahl immer wieder neu berechnet werden muss. Ich könnte mir vorstellen, dass du Zeit gewinnst, wenn du den Speicherblock einmal von vorn bis hinten durchläufst und dabei immer 10 aufeinander folgende Zeichen zu einer Zahl zusammensetzt.

Ist das Format der Datei fest vorgegeben? Sonst fände ich es wesentlich geschickter, die Zahlen nicht als String zu speichern, sondern binär.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1051
Wohnort: Ruhrpott

BeitragVerfasst am: 10.07.2020, 18:08    Titel: Antworten mit Zitat

@nemored: Auch für binäre Daten ziehe ich wenn irgend möglich einen String als Speicherort vor, weil ich mir dabei um die Speicherverwaltung keinen Kopf machen muß.

@pzktupel: Um den Zugriff auf den Datenstring zu beschleunigen, muß man ein weinig in die Trickkiste greifen:
Code:
Dim As ZString Ptr zp
Open "E:\TUPEL\3TEX777.bin" For Binary Access Read As #1

Print Timer
While Not Eof(1)
   S=Input(20000000, #1)
   For v=1 To 20000000 Step 20
      'M1=Val(Mid(S,v,10))
      S[v + 8] = 0 'ende - kennzeichnung für ZSting setzen
      zp = StrPtr(S) + v - 1 'pointer auf anfang der gewünschten zahl setzen
      M1=Val(*zp) 'wert über dereferenzierten pointer holen
            
      'M2=Val(Mid(S,v+10,10))
      S[v + 18] = 0
      zp = StrPtr(S) + v + 9
      M2=Val(*zp)
      'Print M1,M2:Sleep
   Next v
Wend

Print Timer
Close #1
Voraussetzung ist natürlich, daß jede Zahl exakt 8 Stellen hat.

Es gibt noch einen anderen Trick, allerdings weiß ich nicht, wie es damit geschwindigkeitsmässig aussieht. Du kannst ja mal beides ausprobieren:
Code:
Type tTrick
   Union
      As String*20000000 S 'datenstring
      As String*9 t(1 To 1000000) 'array von 10-byte-strings
   End Union
End Type

Dim Shared As tTrick ar

Open "E:\TUPEL\3TEX777.bin" For Binary Access Read As #1

Print Timer
While Not Eof(1)
   ar.S=Input(20000000, #1)
   For v=1 To 1000000 Step 2
      m1 = Val(ar.t(v))
      m2 = Val(ar.t(v + 1))
      
      'Print M1,M2:Sleep
   Next v
Wend

Print Timer
Close #1

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 43

BeitragVerfasst am: 10.07.2020, 19:24    Titel: Antworten mit Zitat

Schön !

Ich habe heute den ganzen Tag beknobelt und ich konnte auch tatsächlich dank eurer Hilfe Speed x6 erreichen.
Was passierte ?
Diese Idee mit den blockweise einlesen klappte richtig gut. Ich formatierte alle Zahlen auf 10 Stellen konnte mit "VALUINT" die schnellste Konvertierung zu einer Integer erreichen. Mit VAL ist das langsamer !
Ins scharfe Sieb konnte ich das auch schon erfolgreich einbinden.
3 GB File mit 274 Mio Zahlen ist in 80s ausgelesen und verarbeitet, vorher 8min 20s.

Hier der Code:
Open "E:\TUPEL\3TEX1899.txt" for Binary Access Read As #1

PRINT timer
WHILE NOT EOF(1)
S=INPUT(1000000,#1)
i=1
WHILE i<1000000
M1=VALUINT(MID(S,i,10))
M2=VALUINT(MID(S,i+10,10))
i+=20
WEND
WEND
print timer
CLOSE #1
SLEEP


Dank Euche ! lächeln
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4372
Wohnort: ~/

BeitragVerfasst am: 10.07.2020, 20:10    Titel: Antworten mit Zitat

pzktupel hat Folgendes geschrieben:
Ich formatierte alle Zahlen auf 10 Stellen konnte mit "VALUINT" die schnellste Konvertierung zu einer Integer erreichen. Mit VAL ist das langsamer !

Klingt im Nachhinein logisch. VALUINT formatiert zu einer Ganzzahl und kann abbrechen, sobald es auf ein Nichtziffernzeichen stößt (vom Start mit "-" oder "&" abgesehen), wogegen VAL auch den Dezimalpunkt und die wissenschaftliche Notation berücksichtigen muss - da hat der Parser mehr Entscheidungsregeln.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 43

BeitragVerfasst am: 10.07.2020, 20:35    Titel: Antworten mit Zitat

Das leuchtet ein ! Ihr seid die Profies grinsen

Etwas Eigenwerbung...

Man kann fragen, warum das ganze ?

Ich programmiere die schnellsten Primzahl-k-Tupel Siebe, nur kommt man an Grenzen, die immer wiedermal optimiert werden müssen.

Auf MP finden sich die Resulte:

https://matheplanet.de/matheplanet/nuke/html/viewtopic.php?topic=232720&start=0

Das größte Sahnebonbon waren die beiden Offset zu finden für das kleinste 100stellige Primzahl-10-Tupel beider Typen,unter Freebasic versteht sich.

Es ist:
10^99+84878086452295590307+d , d=0,2,6,12,14,20,24,26,30,32
10^99+707220670972957883551+d , d=0,2,6,8,12,18,20,26,30,32

Grüße

@nemored mit binär muss ich nochmal testen, ist eben ungünstig,weil ich
nur maschinencode so sehe...so wie es jetzt ist,ist auch gut.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
pzktupel



Anmeldungsdatum: 07.07.2020
Beiträge: 43

BeitragVerfasst am: 10.07.2020, 22:43    Titel: Antworten mit Zitat

Ich komm hier bei einer Unstimmigkeit nicht weiter....

Der code von @nemored klappt nur bedingt...bug ???

Abgesehen davon, habe ich aus *9 in *10 geändert

Type tTrick
Union
As String*20000000 S 'datenstring
As String*10 t(1 To 2000000) 'array von 10-byte-strings
End Union
End Type

ar.S=Input(20000000, #1)
k=1
For ii=1 TO 2000000 STEP 10
PRINT VAL(ar.t(k));:SLEEP
k+=1
NEXT ii

Wenn ich aus meiner Liste lese:
0 10 14 9 4 12 21 16 9 3 16 29 0 30 22 38 19 18 17 20 45 41 5 13 23 23 32 23 13 28 0 59 56 54 19 6 82 67 62 27 0 70 52 7 72 90 41 83 60 61 84 37 48 101 0 101 84 21 32 147...

Dann erhalte ich:
0 10 14 9 4 12 21 16 9 3 ?? 29 0 30 22 38 19 18 17 20 ???(5) 5 13 23 23 32 23 13 28 0 9 54 19 6 82 67 62 27 0 70 2 72 90 41 83...

Fällt was auf ? Da passen etliche nicht,wieso ?

16, (45 41),...
Keine Panik, die Zahlen haben eine Bedeutung !

0 spezifischer Einstiegspunkt zur 13
10 : 13 teilt 10*11#+1

14 spezifischer Einstiegspunkt zur 17
9 : 17 teilt 9*11#+1

4 spezifischer Einstiegspunkt zur 19
12 : 19 teilt 12*11#+1

Hoch komplex... verlegen

Allerding über die meinige Methode
WHILE NOT EOF(1)
S=INPUT(1000000,#1)
v1+=1
i=1
WHILE i<1000000
V=M1
M1=VALUINT(MID(S,i,10))
M2=VALUINT(MID(S,i+10,10))
PRINT M1;" ";M2;" ";:SLEEP
i+=20
WEND
WEND
erhalte ich:
0 10 14 9 4 12 21 16 9 3 16 29 0 30 22 38 19 18 17 20 45 41 5 13 23 23 32 23 13 28 0 59 56 54 19 6 82 67 62 27 0 70 52 7 72 90
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1051
Wohnort: Ruhrpott

BeitragVerfasst am: 11.07.2020, 09:46    Titel: Antworten mit Zitat

pzktupel hat Folgendes geschrieben:
Abgesehen davon, habe ich aus *9 in *10 geändert
Und genau das ist der Fehler. Die *9 ist schon richtig, weil FB intern noch ein Nullbyte als Terminator dranhängt (im Gegensatz zum ZString, wo das dem Programmierer überlassen wird):
Code:
Dim As ZString*9 zs
Print SizeOf(zs)

Dim As String*9 fs
Print SizeOf(fs)

Sleep
Und ja, nach solchen Fehlern kann man sich totsuchen.

Übrigens kannst du dir bei Verwendung von VALUINT das Nullsetzen des Terminatorbytes
Code:
S[v + 8] = 0 'ende - kennzeichnung für ZSting
beim Pointerzugriff sparen. Und die Pointerberechnung kannst du direkt in die Klammer setzen.
Code:
M1=ValUInt(*(StrPtr(S) + v - 1))
Das könnte auch nochmal ein paar Mikrosekunden Zeitersparnis bringen.

Mich würde mal ein Geschwindigkeitsvergleich Pointer vs. UNION interessieren. Meiner Erfahrung nach ist bei FB der Pointerzugriff von der Geschwindigkeit her unschlagbar. Ich nutze diese Daten-in-String-laden-und-dann-mit-Pointer-dran-entlangfahren-Methode zum Normalisieren von Musikdateien.

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz