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?
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
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.
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.
Jens schrieb:> Warum ist x unterschiedlich?
Weil es zwei völlig unterschiedliche Operationen sind - sagt meine
Blitzbirne.
> x = Byte >> 4;
x wird um 4 Bits nach rechts verschoben.
Aus 11001000 wird 00001100.
> x = Byte & 0xF0;
Aus 11001000 wird 11000000.
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. :)
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...
c-hater schrieb:> Aber davon, das zu verstehen, bist du mindest so weit entfernt, wie> Alpha Centauri von Sol. Lichtjahre...
Und deine "Erklärung" trägt nicht dazu bei, die beiden näher zusammen zu
bringen.
BTW: wie weit bist du mit deinem Knigge schon gekommen? Ein Tipp: man
kann da umblättern, der hat mehrere Seiten...
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.