Hallo, ich bin µC Anfänger und habe folgende Frage zum Vergleichen von Variablen: So weit ich weiß sind Vergleiche eines beliebigen Werts X mit einem Wert Y der (2^n)-1 oder -(2^n) ist schneller als wie wenn Y beliebig ist. Weiß jemand warum? Der C-Code meiner Frage sieht also quasi so aus: Schnell: if(X => 512) {....} // Y = 2^9 Langsam: if(X => 500) {....} // Y = 500 Muss für den schnellen Vergleich nur eine Variable ins Register geladen werden, die dann ensprechend geshiftet und dann auf 0 geprüft wird? Ich habe mal versucht anhand der Dokumentation des von mir genutzten TI TMS470 nachzuvollziehen wie viele clock-cycles für einen CMP Befehl benötigt werden, aber alleine bekomme ich das nicht hin... Noch eine kurze 2.Frage/Vermutung: Ich vermute durch die bedingten Sprungbefehle im ARM-Mode ist der Unterschied zwischen schneller/langsmer Variante wengier ausgeprägt als im Thumb-Mode, oder? Vielen Dank im Voraus, Daniel
> Schnell: if(X => 512) {....} // Y = 2^9
Evtl weil nur geprüft werden muss, ob das Bit 2^9 von X gesetzt ist.
Sonst fällt mir kein Grund ein.
>ich bin µC Anfänger und habe folgende Frage zum Vergleichen von >Variablen: Stell diese Frage wieder, wenn Du Profi geworden bist und die Antwort dringend zur Problemlösung benötigt wird. Gerade als Anfänger ist es nicht sinnvoll, virtuelle Probleme zu lösen.
>So weit ich weiß sind Vergleiche eines beliebigen Werts X mit einem Wert >Y der (2^n)-1 oder -(2^n) ist schneller als wie wenn Y beliebig ist. Weil man bei diesen speziellen Werten möglicherweise nur 1 Bit vergleichen muss. Die modernen Prozessoren vergleichen immer 8, 16 oder mehr Bit auf einmal und da macht es keinen Unterschied mehr.
>Der C-Code meiner Frage sieht also quasi so aus: >Schnell: if(X => 512) {....} // Y = 2^9 >Langsam: if(X => 500) {....} // Y = 500 Ein 16bit Vergleich (cp, cpc) ist ein 16bit Vergleich. Das dauert immer gleich lange. Ist also egal, mit welcher (16bit) Zahl verglichen wird!
Ich denke es hat einen anderen Grund: Bei >= 512 muss mindestens Bit 9 oder ein höheres gesetzt sein. Es reicht also das high Byte auf >=2 zu Prüfen, es ist also ein 8bit Vergleich. Bei >500 muss man dagegen auch das Lowbyte mit einbeziehen, also ist ein 16bit Vergleich notwendig
Benedikt K. wrote: > Ich denke es hat einen anderen Grund: > Bei >= 512 muss mindestens Bit 9 oder ein höheres gesetzt sein. Es > reicht also das high Byte auf >=2 zu Prüfen, es ist also ein 8bit > Vergleich. > Bei >500 muss man dagegen auch das Lowbyte mit einbeziehen, also ist ein > 16bit Vergleich notwendig Nu ist der TMS470 aber ein 32-Bitter, wenn ich mich nicht ganz irre, und bei dem sollte es keinen Unterschied machen, ob ein 8-, 16- oder 32-Bit-Vergleich... Bei einer 8-Bit-Architektur stimme ich Dir zu, da muss bei solchen Vergleichen mit 2^n jeweils nur ein Bit in einem Byte überprüft werden.
Johannes M. wrote:
> Vergleichen mit 2^n jeweils nur ein Bit in einem Byte überprüft werden.
Wiso schreiben das alle ? Das ist doch falsch !
Was ist wenn z.B. die Zahl den Wert 1024 hat ? Dann reicht es nicht das
512er Bit zu prüfen, wenn man >= haben möchte !
right... *g naja mein Hirn is heute nimmer so auf der Hoehe :D Natuerlich musste Bits, die hoeher sind da auch beruecksichtigen...
Benedikt K. wrote: >> Vergleichen mit 2^n jeweils nur ein Bit in einem Byte überprüft werden. > > Wiso schreiben das alle ? Das ist doch falsch ! > Was ist wenn z.B. die Zahl den Wert 1024 hat ? Dann reicht es nicht das > 512er Bit zu prüfen, wenn man >= haben möchte ! Richtig, aber es muss trotzdem nur das High-Byte berücksichtigt werden (also nur ein Byte anstatt zweier)! Und das ist bei einer 8-Bit-Architektur deutlich schneller als der Vergleich zweier Bytes. Aber wie gesagt: Bei einer 32-Bit-Architektur sollte es bei dem obigen Beispiel keinen Unterschied machen. Erst, wenn es an Werte > 32 Bit geht.
Ein Vergleich wird mit Hilfe einer Substraktionsfunktion durchgeführt. Dabei wird Y von X abgezogen. Ist das Ergebnis 0, waren beide Werte gleich gross. Dementsprechend war X grösser Y, wenn es in der Subtraktion einen 0-Durchlauf (Carryflag) gegeben hat. usw. Vergleiche finden also Hauptsächlich in der ALU statt. Die Verarbeitungsgeschwindigkeit gängt demnach von der Bitbreite der ALU ab. Nämlich ob diese die Werte in einem Rutsch verarbeiten kann oder ob dafür mehrere "Anläufe" nötig sind.
Habe einfach das mal Compiliert und angeschaut, was der Compiler daraus macht:
1 | 62: if(X >= 0)bla(); |
2 | 0x0008052C E5950034 LDR R0,[R5,#0x0034] |
3 | 0x00080530 E59F41CC LDR R4,[PC,#0x01CC] |
4 | 0x00080534 E3500000 CMP R0,#0x00000000 |
5 | 0x00080538 BA000000 BLT 0x00080540 |
6 | 0x0008053C EBFFFFD5 BL bla(0x00080498) |
7 | 63: if(X >= 512) bla(); // Y = 2^9 |
8 | 0x00080540 E5950034 LDR R0,[R5,#0x0034] |
9 | 0x00080544 E3500C02 CMP R0,#0x00000200 |
10 | 0x00080548 BA000000 BLT 0x00080550 |
11 | 0x0008054C EBFFFFD1 BL bla(0x00080498) |
12 | 64: if(X >= 500) bla(); // Y = 500 |
13 | 0x00080550 E5950034 LDR R0,[R5,#0x0034] |
14 | 0x00080554 E3500F7D CMP R0,#0x000001F4 |
15 | 0x00080558 BA000000 BLT 0x00080560 |
16 | 0x0008055C EBFFFFCD BL bla(0x00080498) |
17 | 65: if(X >= 0x12345)bla(); |
18 | 0x00080560 E5950034 LDR R0,[R5,#0x0034] |
19 | 0x00080564 E59F119C LDR R1,[PC,#0x019C] |
20 | 0x00080568 E1500001 CMP R0,R1 |
21 | 0x0008056C BA000000 BLT 0x00080574 |
22 | 0x00080570 EBFFFFC8 BL bla(0x00080498) |
23 | 66: Port_init(); |
24 | 0x00080574 EBFFFF32 BL Port_init(0x00080244) |
25 | |
26 | |
27 | |
28 | |
29 | 0x00080700 00010514 DD 0x00010514 |
30 | 0x00080704 FFFFF460 DD 0xFFFFF460 |
31 | 0x00080708 00012345 DD 0x00012345 |
32 | 0x0008070C 000800FC DD 0x000800FC |
33 | 0x00080710 0008011C DD 0x0008011C |
Der Arm7 kann 8 Bit-Konstanten im Befehl enthalten haben, die dann um 2,4,6,..32 Bits nach links geschoben werden können. Hier im Beispiel wird 0x7D durch zwei mal links schieben zu 0x1F4 gleich 500 dezimal. Wenn der Wert so beliebig ist, das er nicht mit 8Bit und 2*N linksschieben erzeugt werden kann (0x12345), dann wird ein 32-Bit-Wert aus dem Programmspeicher gelesen. Das würde dann etwas länger dauern.
Peter X. wrote: > Habe einfach das mal Compiliert und angeschaut, was der Compiler daraus > macht: Wozu? Ich glaube, es ging eher um die prozessorinterne Verarbeitung als um Assemblercode. > Wenn der Wert so beliebig ist, das er nicht mit 8Bit und 2*N > linksschieben erzeugt werden kann (0x12345), dann wird ein 32-Bit-Wert > aus dem Programmspeicher gelesen. Das würde dann etwas länger dauern. Das ist abhängig von der internen Busbreite, aber im Prinzip ist davon auszugehen, das ein 32-Bit-Prozessor einen 8-BitWert genauso schnell einließt wie einen 32Bit-Wert; nämlich in einem Zyklus.
Niels Hüsken wrote: > Das ist abhängig von der internen Busbreite, aber im Prinzip ist davon > auszugehen, das ein 32-Bit-Prozessor einen 8-BitWert genauso schnell > einließt wie einen 32Bit-Wert; nämlich in einem Zyklus. Ja eben nicht, wie das Beispiel oben zeigt. Bei einem 8-Bit-Wert kann dieser Teil des Befehles sein. Bei einem 32-Bit-Wert ist ein extra Wort aus dem Programmspeicher zu lesen. Die Befehle brauchen auch mehr als einen Zyklus, je nachdem ob sie auf dem Flash oder aus dem RAM geholt werden.
x >= C ist bei praktisch allen Prozessoren optimierbar, wenn C konstant, C=m*2**n und n größer oder gleich der Wortbreite des Prozessors ist. Dann kann die Anzahl der benötigten Compare-Befehle auf Maschinenebene reduziert werden. Ansonsten gibt es prozessorspezifische Optimierungsmöglichkeiten wie das von Peter X. angeführte Beispiel für einen ARM.
Vielen Dank schon mal an alle die mir bislang geholfen haben! Peter X. wrote: > Bei einem 8-Bit-Wert kann dieser Teil des Befehles sein. > ... > Die Befehle brauchen auch mehr als einen Zyklus, je nachdem ob sie auf > dem Flash oder aus dem RAM geholt werden. ...genau darauf zielt meine Frage ab! Wie bereits schon richtig vermutet ist der TMS470 ist ein 32 bitter (der ARM und THUMB unterstützt). Eine Optimierung bei 2^n Werten hätte ich auch erst mal beim Compiler vermutet (wie ja der Assembler-Code auch zeigt), erst in zweiter Linie beim µC. Leider bin ich jetzt irgendwie immer noch nicht wirklich schlauer, da ja die eigentliche Frage noch nicht ganz geklärt ist. Ich hänge mal ein Datenblatt an dem ich an, vielleicht versteht ja einer mehr davon als ich...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.