Schnellere Alternative zu StrD()?
Schnellere Alternative zu StrD()?
Ich speichere Messdaten als CSV-Datei, und wollte die zuständige Prozedur optimieren. Das Verarbeiten und Speichern von 1 MB dauert 15 Sekunden.
Ich verwende viermal StrD(x,14), und das kostet 12 Sekunden. Ersetze ich StrD() als Test mit Str(), dauert die Verabeitung nur 3 Sekunden.
Kann man StrD() beschleunigen, gibt es da Tricks?
Peter
			
			
									
									
						Ich verwende viermal StrD(x,14), und das kostet 12 Sekunden. Ersetze ich StrD() als Test mit Str(), dauert die Verabeitung nur 3 Sekunden.
Kann man StrD() beschleunigen, gibt es da Tricks?
Peter
- NicTheQuick
 - Ein Admin
 - Beiträge: 8816
 - Registriert: 29.08.2004 20:20
 - Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
 
Re: Schnellere Alternative zu StrD()?
Wie hast du die Zeit gemessen? Warst du dabei im Debug-Modus? Falls ja, versuch es doch mal ohne. Dann hast du oftmals schon einen gehörigen Geschwindigkeitsunterschied.
Ansonsten bin ich unsicher, ob man mit einer eigenen Implementierung von StrD() irgendwas verbessern könnte. Ich vermute ja eher nicht.
			
			
									
									
						Ansonsten bin ich unsicher, ob man mit einer eigenen Implementierung von StrD() irgendwas verbessern könnte. Ich vermute ja eher nicht.
Re: Schnellere Alternative zu StrD()?
Gemessen wurde mit der kompilierten Exe. Mich hat der große Zeitanteil von StrD() überrascht, da brauche ich nichts optimieren, ist sinnlos.
Peter
			
			
									
									
						Peter
Re: Schnellere Alternative zu StrD()?
Etwas komisch, der folgende Code speichert 1MB mit 60000 StrD() Zahlen und er dauert 55 ms!!DePe hat geschrieben:Das Verarbeiten und Speichern von 1 MB dauert 15 Sekunden.
Code: Alles auswählen
Define Time = ElapsedMilliseconds()
CreateFile(1, GetTemporaryDirectory()+"test.csv")
Define N, M
For N = 1 To 6000
	For M = 1 To 10
		WriteString(1, StrD(Random(100000000)*0.000001, 14)+#TAB$)
	Next
	WriteStringN(1, "")
Next
CloseFile(1)
MessageRequester("1MB", Str(ElapsedMilliseconds()-Time)+" ms")PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
						Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Re: Schnellere Alternative zu StrD()?
was hälst Du hiervon:
viel Erfolg bei der Millisekunden-Jagdt...
			
			
									
									Code: Alles auswählen
#NKS_Faktor=100000000000000 ;14 Nullen (zu wenig für Regierungs-Bildung, für Deinen Zweck sollte es reichen...)
a.d=12.34500000006789
Debug a
b.q=a*#NKS_Faktor ;das ist nun Str()-fähiges Format
Debug b
c.d=b/#NKS_Faktor ;Rückwandlung in Doubl-Format
Debug c
  
Re: Schnellere Alternative zu StrD()?
Hier ist der Code. Es fehlt jetzt einiges, das hat aber keinen Einfluss auf die Geschwindigkeit.
Es wird ein MB vom Speicher eingelesen, berechnet, der Text erstellt und gespeichert. Das Erstellen von dem Text dauert 13 Sekunden, der Rest 2 Sekunden. Ersetze ich StrD() oder entferne es, bin ich gesamt bei 3 Sekunden. Die Prozedur läuft in einem Thread, darum das PostEvent() für den Fortschritt. Gemessen habe ich nur diese For-Schleife.
r* sind Double-Variablen.
Peter
			
			
									
									
						Es wird ein MB vom Speicher eingelesen, berechnet, der Text erstellt und gespeichert. Das Erstellen von dem Text dauert 13 Sekunden, der Rest 2 Sekunden. Ersetze ich StrD() oder entferne es, bin ich gesamt bei 3 Sekunden. Die Prozedur läuft in einem Thread, darum das PostEvent() für den Fortschritt. Gemessen habe ich nur diese For-Schleife.
r* sind Double-Variablen.
Peter
Code: Alles auswählen
For iOffset = iBlockformatLength To iCalc Step 2
  rPoint1 = PeekB(\pData + iOffset)
  rPoint2 = PeekB(\pData + iOffset + 1)
  rPoint1 = (rPoint1 * (rVerticalScale / #rCodePerDiv)) - rVerticalOffset
  rPoint2 = (rPoint2 * (rVerticalScale / #rCodePerDiv)) - rVerticalOffset
  rPointTime1 = rTimeValue + (rPointNumber * rHorizontalInterval)
  rPointTime2 = (rPointTime1 + rHorizontalInterval)
  rPointNumber + 1
  sText = Str(iCount) + sComma + RTrim(StrD(rPointTime1, #iSaveDataNbDecimal), #sChar0) + sComma + StrD(rPoint1) + EndOfLine
  iCount + 1
  sText + Str(iCount) + sComma + RTrim(StrD(rPointTime2, #iSaveDataNbDecimal), #sChar0) + sComma + StrD(rPoint2) + EndOfLine
  rPointNumber + 1
  WriteString(iFileNumber, sText)
  cProgress + 1
  If (cProgress = 1000)
    cProgress = 0
    If ((ElapsedMilliseconds() - iTimeProgress) >= #iSaveDataTimeWaitProgress)
      iTimeProgress = ElapsedMilliseconds()
      iCalc2 = (iProgressEnd - iProgressStart)
      If (iCalc2 <= 0) : iCalc2 = 100 : EndIf
      iCalc2 = (iChannelDataSize / iCalc2)
      If fLogic
        iCalc2 / 2
      EndIf
      If (iCalc2 <= 0) : iCalc2 = iChannelDataSize : EndIf
      iCalc2 = (iCount / iCalc2)
      If (iCalc2 > iProgress)
        iProgress = iCalc2
        PostEvent(#eEventCustomSaveDataThread, *uInstance\iWindowNumber,
                  iInstanceNumber, #eThreadEventProgress, (iProgress + iProgressStart))
      EndIf
    EndIf
    If (*uInstance\eSaveDataThreadStatus = #eThreadStatusCancel) Or
       (*uInstance\eSaveDataThreadStatus = #eThreadStatusEnd)
      Break
    EndIf
  EndIf
Next                                                                                                                        
Re: Schnellere Alternative zu StrD()?
Hallo!
Versuche das hier mal:
			
			
													Versuche das hier mal:
Code: Alles auswählen
DisableDebugger
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  ImportC ""
    _gcvt(x.d, ndigit.l, *buf)
  EndImport
CompilerElse
  ImportC ""
    gcvt(x.d, ndigit.l, *buf)
    _gcvt(x.d, ndigit.l, *buf) As "_gcvt"
  EndImport
CompilerEndIf
StartTime.q = ElapsedMilliseconds()
Define StrDouble.s
Define StrBuffer.s{32}
Define ValDouble.d
For i = 0 To 1000000
  ValDouble = i + 0.123456789
  
  _gcvt(ValDouble, 32, @StrBuffer)
  
  ;StrD(ValDouble)
Next
MessageRequester("Test", Str( ElapsedMilliseconds() - StartTime ) + ~"\n"+ PeekS(@StrBuffer, -1, #PB_UTF8))
;MessageRequester("Test", Str( ElapsedMilliseconds() - StartTime ) + ~"\n"+ StrDouble)
					Zuletzt geändert von ccode_new am 03.11.2020 23:19, insgesamt 3-mal geändert.
									
			
									Betriebssysteme: div. Windows, Linux, Unix - Systeme
no Keyboard, press any key
no mouse, you need a cat
						no Keyboard, press any key
no mouse, you need a cat
- NicTheQuick
 - Ein Admin
 - Beiträge: 8816
 - Registriert: 29.08.2004 20:20
 - Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
 
Re: Schnellere Alternative zu StrD()?
@sibru
Sowas geht schnell schief, weil Doubles wesentlich höhere Werte annehmen können als Quads. Und sie können so klein werden, dass die Zahl multipliziert mit 10^14 immer noch kleiner als 0 ist.
@DePe
Also schreibst du nicht 1MB raus, sondern liest 1MB an Daten ein, und aus jedem Byte wird eine Zeile in der resultierenden Datei? Dass das lange dauert, kann ich mir vorstellen.
 
Du hast also am Ende 1 Mio. Zeilen, die so oder so ähnliche aussehen:
			
			
									
									
						Sowas geht schnell schief, weil Doubles wesentlich höhere Werte annehmen können als Quads. Und sie können so klein werden, dass die Zahl multipliziert mit 10^14 immer noch kleiner als 0 ist.
@DePe
Also schreibst du nicht 1MB raus, sondern liest 1MB an Daten ein, und aus jedem Byte wird eine Zeile in der resultierenden Datei? Dass das lange dauert, kann ich mir vorstellen.
Du hast also am Ende 1 Mio. Zeilen, die so oder so ähnliche aussehen:
Code: Alles auswählen
1,63.12354,45
2,3.123332,33
...Re: Schnellere Alternative zu StrD()?
Das ist immer noch merkwürdig, außer #iSaveDataNbDecimal oder rPointTime1 oder rPointTime2 sind gigantisch groß.
Hast du mal den gegen Check probiert, indem du einfach die Zeile:
zwei mal hintereinander ausführst? Dann sollte es ja von 13s auf etwa 19s springen.
Ich weiß leider nicht wie die ThreadSafe (was du ja sicher angeschaltet hast)-Variante von StrD() aussieht, aber kann mir kaum vorstellen, dass diese dann so viel langsamer sein soll.
Die Idee von sibru klapp natürlich nur bedingt, wenn die Zahl nicht zu groß wird und in eine Quad passt.
EDIT: Den code von ccode_new bekomme ich weder unter x86 noch unter x64 zum laufen, außerdem ist da n Debug drin
			
			
									
									Hast du mal den gegen Check probiert, indem du einfach die Zeile:
Code: Alles auswählen
sText = Str(iCount) + sComma + RTrim(StrD(rPointTime1, #iSaveDataNbDecimal), #sChar0) + sComma + StrD(rPoint1) + EndOfLineIch weiß leider nicht wie die ThreadSafe (was du ja sicher angeschaltet hast)-Variante von StrD() aussieht, aber kann mir kaum vorstellen, dass diese dann so viel langsamer sein soll.
Die Idee von sibru klapp natürlich nur bedingt, wenn die Zahl nicht zu groß wird und in eine Quad passt.
EDIT: Den code von ccode_new bekomme ich weder unter x86 noch unter x64 zum laufen, außerdem ist da n Debug drin
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
						Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
- NicTheQuick
 - Ein Admin
 - Beiträge: 8816
 - Registriert: 29.08.2004 20:20
 - Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
 
Re: Schnellere Alternative zu StrD()?
Der Code ist auch nur für Linux, soweit ich das sehe.STARGÅTE hat geschrieben:EDIT: Den code von ccode_new bekomme ich weder unter x86 noch unter x64 zum laufen, außerdem ist da n Debug drin