Seite 1 von 6
SetBits / GetBits gut genug?
Verfasst: 25.10.2018 16:55
von Mijikai
Hallo ich verwende nachfolgenden Code um 3 Bits in Folge zu schreiben oder zu lesen.
Es funktioniert aber ich vermute das es schneller geht bzw. bessere Methoden gibt.
Ist mein Code so ok oder geht es besser?
Das ganze soll nämlich bei der Bildbearbeitung eingesetzt werden daher sollte es so flott wie möglich sein
Code:
Code: Alles auswählen
;PB v.5.62 x64 (Win 7 / 10)
Procedure.i SetBit(*Target,Bit.i)
!mov rax,[rsp + 30h]
!mov rcx,[rsp + 38h]
!bts [rax],rcx
EndProcedure
Procedure.i GetBit(*Target,Bit.i)
!xor rax,rax
!mov rcx,[rsp + 30h]
!mov rdx,[rsp + 38h]
!bt [rcx],rdx
!setc al
ProcedureReturn
EndProcedure
Procedure.i SetBits(*Target,Offset.i,Value.i)
Select Value
Case 1;001
SetBit(*Target,Offset + 2)
Case 2;010
SetBit(*Target,Offset + 1)
Case 3;011
SetBit(*Target,Offset + 1)
SetBit(*Target,Offset + 2)
Case 4;100
SetBit(*Target,Offset)
Case 5;101
SetBit(*Target,Offset)
SetBit(*Target,Offset + 2)
Case 6;110
SetBit(*Target,Offset)
SetBit(*Target,Offset + 1)
Case 7;111
SetBit(*Target,Offset + 0)
SetBit(*Target,Offset + 1)
SetBit(*Target,Offset + 2)
EndSelect
EndProcedure
Procedure.i GetBits(*Target.Long,Offset.i)
Protected Dim Bit.a(3)
Bit(0) = GetBit(*Target,Offset)
Bit(1) = GetBit(*Target,Offset + 1)
Bit(2) = GetBit(*Target,Offset + 2)
*Target = @Bit()
Select *Target\l
Case 65536
ProcedureReturn 1
Case 256
ProcedureReturn 2
Case 65792
ProcedureReturn 3
Case 1
ProcedureReturn 4
Case 65537
ProcedureReturn 5
Case 257
ProcedureReturn 6
Case 65793
ProcedureReturn 7
EndSelect
EndProcedure
Global Buffer.i
SetBits(@Buffer,0,4);<- setze den Wert 4 (in 3 Bits) an die Position @Buffer + Offset (in Bits)
Debug GetBits(@Buffer,0);<- hier wird der Wert wieder ausgelesen
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 17:42
von ccode_new
Gut genug ?
Da kann ich nicht /möchte ich mich nicht festlegen.
Aber es ist schnell.
Procedure.i SetBit(*Target,Bit.i)
!mov rax,[rsp + 30h]
!mov rcx,[rsp + 38h]
!bts [rax],rcx
EndProcedure
Das ist aber bei mir nicht schneller als:
Procedure SetBit(*T, B.i)
*T + (B >> 3)
PokeB(*T, PeekB(*T) | (1 << (B & 7)))
EndProcedure
Beide Funktionen sind aber eigentlich gleich schnell, oder nur extrem minimal unterschiedlich schnell.
Ich habe nur etwas Komisches festgestellt. Umso kürzer die Variablennamen sind, umso schneller wird der Code.
(Ist aber sehr minimal)
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 17:51
von Sicro
Verwende Macros anstelle der Procedures, um noch ein paar Millisekunden zu sparen.
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 18:30
von NicTheQuick
Genau, wenn es schnell gehen soll, dann verabschiede dich von Procedures. Purebasic erkennt leider nicht von selbst, wann es eine Procedure inline kompilieren kann.
Ansonsten ist dein Select-Case auch sehr kontraproduktiv.
Abgesehen davon bekomme ich einen ungültigen Speicherzugriff beim Starten deines Codes. Das könnte entweder daran liegen, dass Linux hier was anders macht oder dass ich den Purifier immer aktiviert habe.
Ich hätte es wahrscheinlich einfach so gemacht:
Code: Alles auswählen
;PB v.5.62 x64 (Win 7 / 10)
Procedure.i SetBits(*Target.Long, Offset.i, Value.i)
*Target\l | (Value << Offset)
EndProcedure
EndProcedure
Procedure.i GetBits(*Target.Long, Offset.i)
ProcedureReturn (*Target\l >> Offset) & %111
EndProcedure
Global Buffer.l
SetBits(@Buffer,0,3);<- setze den Wert 4 (in 3 Bits) an die Position @Buffer + Offset (in Bits)
Debug GetBits(@Buffer,0);<- hier wird der Wert wieder ausgelesen
Die Procedures waren hier aber praktisch, da ich dann besser eine Struktur anhängen konnte, weil ich Peek und Poke nicht so mag.
Übrigens setze ich hier wirklich nur Bits. Vorhandene 1en werden keine 0, wenn man SetBits benutzt. Aber es war auch nicht ersichtlich wie viele Bits bei dir berücksichtigt werden sollten. Mit einer genaueren Spezifikation kann ich dir vielleicht noch besser helfen.
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 18:52
von Mijikai
ccode_new hat geschrieben:...Beide Funktionen sind aber eigentlich gleich schnell, oder nur extrem minimal unterschiedlich schnell.
Ich habe nur etwas Komisches festgestellt. Umso kürzer die Variablennamen sind, umso schneller wird der Code.
(Ist aber sehr minimal)
Danke für den Geschwindigkeitsvergleich mit anderem Code.
Wie ist das mit den Variablennamen zu Verstehen?
Sicro hat geschrieben:Verwende Macros anstelle der Procedures, um noch ein paar Millisekunden zu sparen.
Danke, werd ich versuchen Leider hab ich noch nie wirklich mit Macros gearbeitet.
NicTheQuick hat geschrieben:...
Übrigens setze ich hier wirklich nur Bits. Vorhandene 1en werden keine 0, wenn man SetBits benutzt. Aber es war auch nicht ersichtlich wie viele Bits bei dir berücksichtigt werden sollten. Mit einer genaueren Spezifikation kann ich dir vielleicht noch besser helfen.
Danke für das alternative Codebeispiel.
Es sollen immer 3 Bits kontinuierlich gelesen bzw. geschrieben werden bis das Ende der Datei erreicht ist.
Mit 3 Bits kann ich dann maximal 8 Zustände bzw. Grauwerte abbilden.
Ich hab mal was von Bit-Masken gelesen (es nicht Verstanden) und vermutet, dass es eventuell möglich ist
3 Bits auf einen Schlag zu lesen oder zu schreiben.
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 18:53
von ccode_new
Abgesehen davon bekomme ich einen ungültigen Speicherzugriff beim Starten deines Codes. Das könnte entweder daran liegen, dass Linux hier was anders macht oder dass ich den Purifier immer aktiviert habe.
So ist es auch unter einem anderen Betriebssystem lauffähig. (getestet unter Linux

)
Code: Alles auswählen
Procedure.i SetBit(*Target,Bit.i)
!mov rax,[p.p_Target]
!mov rcx,[p.v_Bit]
!bts [rax],rcx
EndProcedure
Procedure.i GetBit(*Target,Bit.i)
!xor rax,rax
!mov rcx,[p.p_Target]
!mov rdx,[p.v_Bit]
!bt [rcx],rdx
!setc al
ProcedureReturn
EndProcedure
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 18:55
von NicTheQuick
Musst du sequentiell lesen und schreiben oder eher durcheinander? Falls es nur sequentiell laufen soll, dann kann man da viel optimieren. Zum Beispiel 8 mal 3 Bits in einen 3-Byte-Speicherbereich shiften und dann diese 3 Bytes auf einmal schreiben.
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 18:58
von Mijikai
NicTheQuick hat geschrieben:Musst du sequentiell lesen und schreiben oder eher durcheinander? Falls es nur sequentiell laufen soll, dann kann man da viel optimieren. Zum Beispiel 8 mal 3 Bits in einen 3-Byte-Speicherbereich shiften und dann diese 3 Bytes auf einmal schreiben.
Nur sequentiell beim en- und decodiren des Bildes.
Das Problem -> ich muss immer erst einen RGB/A Wert auslesen/einlesen und umwandeln.
Also steppe ich entweder nur 3 oder 4 Bytes durch den Speicher.
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 21:54
von juergenkulow
Hallo Mijikai,
1.DisableDebugger
2.CPU-Takte messen
Code: Alles auswählen
Define T0,T1,T2
EnableASM
RDTSC
mov T0,rax
SetBits(@Buffer,0,4);<- setze den Wert 4 (in 3 Bits) an die Position @Buffer + Offset (in Bits)
RDTSC
mov T1,rax
GetBits(@Buffer,0) ;<- hier wird der Wert wieder ausgelesen
RDTSC
mov T2,rax
EnableDebugger
Debug T2-T1
Debug T1-T0
3. Stimmt die Hex/Bit-Matrix:
$10000 --1
$00100 -1-
$00001 1--
4. LODSD, STOSD brauchbar
5. Schleifen und Call möglichst vermeiden.
6. Tabellen nutzen.
7. Aufteilung auf mehrere CPUs(Threads)
8. GPU-Aufgabe?
9. Verwendung von 6 Byte 48 Bit 16x3 Bit (Octel) prüfen
Gruß
Re: SetBits / GetBits gut genug?
Verfasst: 25.10.2018 22:03
von ccode_new
@juergenkulow
Für Punkt 7 und 8 hätte ich ja gerne mal Beispiele.
