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: 8807
- 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: 8807
- 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) + EndOfLine
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

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: 8807
- 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