SetBits / GetBits gut genug?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

SetBits / GetBits gut genug?

Beitrag 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
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: SetBits / GetBits gut genug?

Beitrag 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)
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: SetBits / GetBits gut genug?

Beitrag von Sicro »

Verwende Macros anstelle der Procedures, um noch ein paar Millisekunden zu sparen.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: SetBits / GetBits gut genug?

Beitrag 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. :-D

Ü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.
Bild
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: SetBits / GetBits gut genug?

Beitrag 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. 8)
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. :freak:
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.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: SetBits / GetBits gut genug?

Beitrag 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
Zuletzt geändert von ccode_new am 25.10.2018 19:11, insgesamt 1-mal geändert.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: SetBits / GetBits gut genug?

Beitrag 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.
Bild
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: SetBits / GetBits gut genug?

Beitrag 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.
Benutzeravatar
juergenkulow
Beiträge: 188
Registriert: 22.12.2016 12:49
Wohnort: :D_üsseldorf-Wersten

Re: SetBits / GetBits gut genug?

Beitrag 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ß
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: SetBits / GetBits gut genug?

Beitrag von ccode_new »

@juergenkulow

:allright:

Für Punkt 7 und 8 hätte ich ja gerne mal Beispiele. :wink:
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Antworten