Bit schieben oder vergleichen

Gast #5623420
Lesenswert?

Hallo,
ich habe mal eine Interessensfrage. Da ich nichts habe, womit ich das 
messen könnte, wollte ich mal nachfragen, ob das hier jemand weiß.
Ich möchte z.B. die oberen 4 Bits von einem Byte wissen. Dazu habe ich 
nun zwei möglichkeiten:
1
x = Byte >> 4;
2
x = Byte & 0x0F;

Welche Berechnung wäre bei sowas schneller? Und welche Schreibweise wird 
bevorzugt?
#5623430
Lesenswert?

dir ist aber schon klar, dass x in den beiden fällen nacher nicht den 
gleichen inhalt hat? also wird es wohl auch darauf ankommen, wie x 
weiter verarbeitet werden soll.
und letztlich wird/kann es wohl auch von der verwendeten CPU architektur 
abhängig sein ...

vG Alram
Gast #5623441
Lesenswert?

Um solche Fragen zu klären schreibe ich ein kleines Testprogramm und 
lasse mir vom Compiler das Listing des erzeugten Assembler Codes 
ausgeben. Dann schaue ich in der Doku 
(http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf) 
nach, wie viele Takte die verwendeten Assembler-Befehle benötigen.

Falls du eine Vorlage für das Makefile brauchst: 
http://stefanfrings.de/avr_hello_world/index.html
Gast #5623454
Lesenswert?

Alram L. schrieb:
> und letztlich wird/kann es wohl auch von der verwendeten CPU architektur
> abhängig sein ...

Ok, dass kann ich verstehen

Alram L. schrieb:
> dir ist aber schon klar, dass x in den beiden fällen nacher nicht den
> gleichen inhalt hat? also wird es wohl auch darauf ankommen, wie x
> weiter verarbeitet werden soll.

Warum ist x unterschiedlich? Und warum kommt es auf der 
weiterverarbeitung drauf an?

Stefanus F. schrieb:
> Um solche Fragen zu klären schreibe ich ein kleines Testprogramm und
> lasse mir vom Compiler das Listing des erzeugten Assembler Codes
> ausgeben.

Danke, werde ich auch mal versuchen.
Gast #5623465
Lesenswert?

Also Zusammengefasst:
- Es sind zwei unterschiedliche Funktionalitäten
- Es hängt davon ab, welchen Controller Du hast, welchen Compiler und 
welche (Optimierungs-)Einstellungen
- Es hängt davon ab, was davor und danach mit Byte oder X geschieht 
(also ob und welche Zwischenergebnisse sowieso noch gebraucht werden)
- Es hängt auch davon ab, ob BYTE signed ist (beim >>, falls der µC 
Nibbles swappen kann) und welche größe X hat.

In den meisten Fällen sollte die Bitmaske besser oder gleich gut sein. 
Oder anders: Es ist unwahrscheinlich, dass die Schiebeoperation weniger 
Takte braucht.

Wenn es voraussichtlich weniger als 1000 Mal Pro Sekunde pro MHz 
aufgerufen wird, ist das Ergebnis für reale Software wohl kaum relevant.

Wenn es mehr Aufrufe werden, geht auch Messen zur Laufzeit mit µs-Ticker 
(1000 Aufrufe, sicherstellen, dass sie nicht wegoptimiert werden, vorher 
und nacher einen Counter mit ~µs-Auflösung auslesen und Differenz 
bilden.) Mal die eine Version, dann die andere, jeweils in ihrem 
"natürlichen" Kontext.
#5623488
Lesenswert?

Jens schrieb:
> Warum ist x unterschiedlich? Und warum kommt es auf der
> weiterverarbeitung drauf an?

du willst wissen, welche von zwei varianten schneller ist. das geht 
erstmal nur, wenn die beiden letztlich auch das gleiche ergebnis 
liefern.

und deine beiden codezeilen liefern nicht das gleiche ergebnis. damit 
sind sie nicht vergleichbar.

nimm mal an Byte hat den wert 0b11000011:

x = Byte >> 4;
dann hat x nacher den wert 0b00001100

x = Byte & 0xF0;
dann hat x nacher den wert 0b11000000

jetzt hast zwei unterschiedliche ergebnisse und bis daher macht ein 
vergleich keinen sinn.

du wirst aber x vermutlich für weitere berechnungen oder tests 
benötigen. und diese müssen sich in den beiden varianten ebenfalls 
unterscheiden. in summe kann sich ein performanceunterschied ergeben. 
Wenn du x nicht weiter verwendest wird dir jeder vernünftige compiler 
den code komplett löschen ... und damit wäre er gleich schnell. :)
Gast #5623491
Lesenswert?

Jens schrieb:

> Warum ist x unterschiedlich?

Weil in einem Fall z.B. aus 0x38 0x30 wird und im anderen 0x03, was 
ziemlich verscheiden voneinander ist.

Du solltest die Sprache lernen, mit der du hantierst!

> Und warum kommt es auf der
> weiterverarbeitung drauf an?

Weil es manchmal halt nützlicher ist, 0x30 zu haben und manchmal 
nützlicher, 0x03 zu haben. Aber davon, das zu verstehen, bist du mindest 
so weit entfernt, wie Alpha Centauri von Sol. Lichtjahre...
Gast #5624908
Lesenswert?

Jens schrieb:
> Ich möchte z.B. die oberen 4 Bits von einem Byte wissen. Dazu habe ich
> nun zwei möglichkeiten:x = Byte >> 4;
> x = Byte & 0x0F;
>
> Welche Berechnung wäre bei sowas schneller? Und welche Schreibweise wird
> bevorzugt?

Ja, WAS möchtest du denn nun genau von den oberen 4 Bit wissen?
1. ob eines davon nicht null ist?
2. ob sie gleich einem gewünschten Bitmuster sind?
3. ob du sie als Nibble weiterverarbeiten willst?

Für 1. geht es eigentlich immer so am einfachsten:
if(x % 0xF0) ..dann...

Für 2. geht es im Prinzip so:
if((x & 0xF0)==MeinMuster) ..dann...

für 3. geht es so:
nib = (x >> 4) & 0xF;

wobei man das Maskieren meistens auch weglassen kann, aber sowas kann 
architekturabhängig sein. Mit dem & 0xF ist man jedoch immer auf der 
sicheren Seite.

Und wie sich das alles in Maschinenbefehlen darstellt, ist nun wirklich 
aus dem C-Quelltext nicht zu entnehmen. Ich hab z.B. beim Keil schon 
Konstrukte für den ARM-Mode gesehen, wo ähnlich zum Fall 1. das etwa so 
ging, daß x zunächst um einige Bit rechtsverschoben und dann 
linksverschoben wurde, was in dem speziellen Falle innerhalb eines 
einzigen Maschinenbefehls ging.

Du kannst also erwarten, daß du aus dem erzeugten Maschinencode oftmals 
nicht mehr ohne längeres Grübeln herausfinden kannst, was da als 
Quellcode gewesen ist. Manchmal geht es auch garnicht mehr.

Und als Schreibweise rate ich dir an, deine Quelle möglichst einfach zu 
schreiben, auch wenn das oftmals mehrere Zeilen ergibt anstelle einer 
schwer zu lesenden Zeile.

Es ist heutzutage auch völlig OK, kompliziertere Zuweisungen in einzelne 
Zuweisungen aufzuteilen - der Compiler optimiert das schon.

W.S.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren