Seite 1 von 1

StrU(g_Array.q(k),#PB_Quad) per ASM optimieren

Verfasst: 30.06.2014 11:04
von hyperG
Das Einlesen von 1GB funktioniert unter 10s,
ABER das Wandeln im Speicher per StrU(g_Array.q(k),#PB_Quad) dauert 3 min??

Code: Alles auswählen

For k=0 To ArraySize.i
    strSum.s =strSum.s+StrU(g_Array.q(k),#PB_Quad)
Next
Achtung: Quelle sind 64 Bit unsigned INT! Zwar können Variablen.q angeblich nur signed (mit Vorzeichen), aber per
StrU(g_Array.q(k),#PB_Quad) scheint die Wandlung auch mit Zahlen > 9223372036854775808 zu funktionieren.

ABER warum ist das so langsam??
Das geht doch per ASM unter 7s, ABER wie?

Re: StrU(g_Array.q(k),#PB_Quad) per ASM optimieren

Verfasst: 30.06.2014 11:13
von NicTheQuick
Bist du sicher, dass du das so machen willst? Einfach Zahlen aneinander hängen, die unterschiedliche Länge haben? Zurückrechnen lässt sich das so ja nicht mehr, weil es keine Trenner zwischen den Zahlen gibt.

Davon abgesehen, ist das Problem bei diesem Stück Code, dass pro Schleifendurchlauf der String immer ein Stückchen erweitert wird. Das heißt pro Schleifendurchlauf muss intern sozusagen ein 'ReAllocateMemory()' gemacht werden, damit der neue String in den Speicher passt. Da es irgendwann nicht mehr möglich ist den String an Ort und Stelle zu erweitern, muss er an eine andere Stelle im Speicher kopiert werden, wo er komplett rein passt. Und da das nun recht häufig passieren wird, ist das ganze so langsam. Die Lösung ist also folgende:
Man sollte schon von Anfang an genug Speicher allozieren und dann den String füllen. Das geht am besten dann mit 'CopyMemoryString()'. Also am Anfang weist man dem String z.B. 'Space(1000000000)' zu und füllt ihn dann von vorne. Oder man arbeitet gleich mit 'AllocateMemory()' und legt den Speicherbereich von Anfang an großzügig fest.

Re: StrU(g_Array.q(k),#PB_Quad) per ASM optimieren

Verfasst: 30.06.2014 12:05
von matbal
Mir ist noch ein Grund eingefallen, warum das Anhängen von Strings in PB so ineffizient ist: Wenn Strings verlängert werden müssen, muß PB herausfinden, wo der String zu Ende ist. Da PB sich die Länge nicht merkt, wird jedes Mal das String-Ende-Zeichen neu gesucht. Demzufolge wird das Anhängen mit zunehmender String-Länge auch dann immer langsamer, wenn selten umkopiert werden muß.

Re: StrU(g_Array.q(k),#PB_Quad) per ASM optimieren

Verfasst: 30.06.2014 12:09
von NicTheQuick
Das stimmt so nicht ganz. Dafür muss PB nicht nach dem Nullbyte suchen.

Code: Alles auswählen

;Unicode deaktivieren!

s.s = "Hallo Welt."	;12 Zeichen inkl. Nullbyte

Debug MemorySize(@s) ;Trotzdem wurde mehr Speicher alloziert
Purebasic weiß ja wie groß der Speicherbereich ist, der gerade für den String benutzt wird. Und nur um den geht es. Es ist irrelevant genau zu wissen wo der String endet.

Re: StrU(g_Array.q(k),#PB_Quad) per ASM optimieren

Verfasst: 30.06.2014 13:15
von matbal
NicTheQuick hat geschrieben:Purebasic weiß ja wie groß der Speicherbereich ist, der gerade für den String benutzt wird.
Das habe ich auch erst gedacht. Das kann aber so nicht stimmen. Wird ein Zeichen im String mit einem Null-Zeichen überschrieben, wird der String auch nur noch bis dahin gelesen. Das geht nur, wenn nach dem String-Ende gesucht wird.

Len() dauert bei langen Strings auch länger als bei kurzen. Das heißt für mich, auch da wird das Ende gesucht.

Übrigens dein Code erzeugt unter Windows den Fehler: Das angegebene "MemoryID" ist ungültig.

Re: StrU(g_Array.q(k),#PB_Quad) per ASM optimieren

Verfasst: 30.06.2014 13:50
von NicTheQuick
Achso, ich weiß jetzt wie du das meintest. Ich war gerade nur bei dem Thema, dass der Speicherbereich des Strings erweitert werden muss, wenn ein viel größerer dran gehängt werden soll. Aber natürlich muss man zum genauen Platzieren des anzuhängenden Strings auch wieder das Nullbyte suchen. Aber theoretisch könnte man danach ja auch von hinten suchen. Das ginge schneller, da man das echte Ende des Speicherbereichs ja kennt.

Unter Linux klappt das mit dem 'MemorySize()' scheinbar mit jeder Art Speicherbereiche, also auch mit Strings. Schade, dass es unter Windows nicht funktioniert. Ich bekomme hier jedenfalls eine Größe von 25 angezeigt.