Hallo, ich möchte gern ein Protokoll (DCC) auslesen. Dazu frage ich bereits 87us nach der steigenden Flanke einen Eingang ab. Der Ablauf soll wie folgt sein: 1: Eingang (PIN_D2) abfragen und negieren 2: Byte um eine Stelle nach links verschieben 3: rechte Stelle mit negiertem Eingang auffüllen dccbit = ~(PIN_D2); dccbyte <<= 1; dccbyte |= dccbit; Hier sind wohl ein paar Fehler enthalten, würde mich über eure Hilfe freuen!! Danke, Philipp
Gast
#5728851
Ich glaube das ist die effizienteste Variante:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
Danke, dieser Code sollte nun das gleiche machen, richtig? dccbit = (~(PIN_D2) & (0x01)); dccbyte1 <<= 1; dccbyte1 |= dccbit; wie finde ich heraus, welcher Code effektiver ist?
Gast
#5728860
Philipp L. schrieb: > dieser Code sollte nun das gleiche machen, richtig? Nein. Du musst das PIND Register Lesen und davon das Bit 2 herausfiltern. Und dann noch an die Position von Bit 0 verschieben, sonst klappt das mit anschliessenden oder-Operation nicht. Diesen Schritt bin ich durch den if() Ausdruck umgangen. Du liest PIN_D2 (was auch immer das sein mag) und filterst davon das Bit 0 heraus.
Gast
#5728865
Stefanus F. schrieb: > Ich glaube das ist die effizienteste Variante: Bedingte Sprünge sind eher selten effizient... wie wäre es damit das komplette Byte auf einmal zu negieren anstatt jedes Bit einzeln?
Gast
#5728869
Dr. Sommer schrieb: > Bedingte Sprünge sind eher selten effizient... Kannst du das am Assembler-Code des AVR konkretisieren? > wie wäre es damit das komplette Byte auf einmal zu negieren > anstatt jedes Bit einzeln? Ja, das könnte eine Abkürzung sein.
> Du liest PIN_D2 (was auch immer das sein mag) und filterst davon das Bit > 0 heraus. PIN_D2 ist doch mittels sbit.h der Eingang PD2 ? diese beiden Zeilen ergeben daher das gleiche, oder nicht? 1: dccbit = (~(PIN_D2) & (0x01)); 2: dccbit = (~(PIND) & (0x03)); > wie wäre es damit das komplette Byte auf einmal zu negieren ich muss aber nach jedem Einlesen auf das einzeln negierte Bit reagieren. Es reicht mir nicht das komplette Byte zu lesen und später als ganzes zu negieren.
Gast
#5728883
Deine sbit.h kann ich nicht berücksichtigen, weil sie mir nicht vorliegt. Unabhängig davon habe ich es ausprobiert:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
Meine angeblich kürzere Variante ist tatsächlich einen Befehl grösser und enthält mehr Sprünge. Dr. Sommer hatte Recht. Am Ende das ganze Byte zu negieren bringt keinen Vorteil.
Gast
#5728924
Philipp L. schrieb: > dccbit = ~(PIN_D2); Ich denke das tut nicht, was du willst, weil es keine echten Bit-Variablen gibt. Du invertierst damit vermutlich alle 8 Bits. Also 0b00000001 oder 0b11111110 Und hier passiert dann im zweiten Fall etwas völlig falsches: > dccbyte |= dccbit;
Gast
#5729049
Der avr-gcc (4.8) Codegenerator ist nicht gerade der Bringer - er erzeugt häufig unnötig komplexen Code. Bei meinem "kanonischen" Ausdruck "x = (x<<1) + !(PIND & (1<<PD2))" erzeugt er miesen Code. Nen einfaches "if" bekommt er aber ganz gut hin:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
Bei höheren Optimierungsstufen (mit loop-unrolling) verkackt er's aber wieder ;-)
Stefanus F. schrieb: > Ich denke das tut nicht, was du willst, weil es keine echten > Bit-Variablen gibt. immer dieser unsinn, das ist raten auf niedrigem niveau! vielleicht mal die doku auch lesen ... z.b. 328p page 22 I/O Registers within the address range 0x00 - 0x1F are directly bit- accessible using the SBI and CBI instructions. In these registers, the value of single bits can be checked by using the SBIS and SBIC instructions. die port register bits lassen sich alle in einer struct exact mappen und ansprechen! viele kennen auch die avr gpioX register nicht und wie diese für flags eingesetzt werden. eure code size kann ich leicht unterbieten, aber ich lass euch das selber rausfinden. für avr verwende ich gcc v8.2! mt
Philipp L. schrieb: > wie finde ich heraus, welcher Code effektiver ist? Indem Du Dir den erzeugten Assembler-Code anschaust.
Gast
#5729235
Stefanus F. schrieb: >> dccbit = ~(PIN_D2); > > Ich denke das tut nicht, was du willst, weil es keine echten > Bit-Variablen gibt. Du invertierst damit vermutlich alle 8 Bits. Apollo M. schrieb: > immer dieser unsinn, das ist raten auf niedrigem niveau! > vielleicht mal die doku auch lesen ... > I/O Registers within the address range 0x00 - 0x1F are directly bit- > accessible using the SBI and CBI instructions. In these registers, the > value of single bits can be checked by using the SBIS and SBIC > instructions. Ich habe von der Programmiersprache C (in der avr-gcc Variante) geschrieben, nicht von diesen Registern. > die port register bits lassen sich alle in einer struct > exact mappen und ansprechen! Das ist aber etwas ganz anderes, als die Zeile Code auf die ich mich bezog. Weisst du: Wenn man einzelne Sätze aus dem Zusammenhang reisst, kann man damit anstellen, was man will - völlig losgelöst von seiner ursprünglichen Bedeutung. Man kann aber auch einfach einen Fantasy Roman schreiben, da besteht immerhin die Möglichkeit, dass sich jemand daran erfreut.
Gast
#5729238
Philipp, würdest du bitte mal die Deklaration der Variable "dccbit" zeigen?
Gast
#5729254
Philipp L. schrieb: > wie finde ich heraus, welcher Code effektiver ist? Früher (tm) hat man dafür die Taktzyklen gezählt, die das Programm für die Ausführung braucht (z.B. im Simulator). Guck dir den Maschinencode an, dann siehst du es oder programmiere es gleich in Inline-Assembler. Ist dein Prozessor am Limit oder warum ist Code-Effizienz bei den paar Takten ein Thema?
Gast
#5729256
@ Apollo M. Warum beachtest du die Netiquette nicht?
1 | |
2 | |
3 | |
Gast
#5729265
Stefanus F. schrieb: > Kannst du das am Assembler-Code des AVR konkretisieren? Es geht um AVR? Da ist der Effekt aufgrund der einfachen Pipeline wahrscheinlich schwächer. Der Effekt ist jedenfalls hinlänglich bekannt, das kannst du einfach googeln.
Beitrag #5729275 wurde von einem Moderator gelöscht.
Beitrag #5729296 wurde von einem Moderator gelöscht.
Gast
#5729335
foobar schrieb: > Nen einfaches > "if" bekommt er aber ganz gut hin: [...] Da fehlt de facto noch eine Instruktion, damit der Code tut, was er soll. Die Initialisierung von r24 auf null. Die dazugerechnet und den Callframe abgezogen ergeben sich 7*6+1*7=49 Takte für den Nutzcode. Das ist nicht gut, das ist schwach. Der richtige Assemblerprogrammierer schreibt hier:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
Das macht dann 8*5=40 Takte, ist also fast 20% schneller. Soviel zum Thema: die C-Compiler sind heute so gut, dass man mit Assembler fast nichts mehr sparen kann. 1/5 der Rechenzeit ist ja wohl doch ein wenig mehr als "fast nichts". > Bei höheren Optimierungsstufen (mit loop-unrolling) verkackt er's aber > wieder ;-) Noch mehr?!
Gast
#5729523
c-hater schrieb: > Da fehlt de facto noch eine Instruktion, damit der Code tut, was er > soll. Die Initialisierung von r24 auf null. Ist nicht nötig - der tut auch so, was er soll.
Gast
#5729558
foobar schrieb: > Ist nicht nötig - der tut auch so, was er soll. Stimmt. lsl schiebt unten natürlich immer eine Null rein. Mein Fehler. OK, steht's also nur noch 40:48. Immer noch 16,7% Gewinn.
Gast
#5729574
> OK, steht's also nur noch 40:48. Immer noch 16,7% Gewinn.
Eigentlich steht's 3:3, denn es ging um "Byte verschieben und mit
Eingang auffüllen". Die Schleife drum herum gehört da nicht zu ;-)
Mit wieviel MHz kommen denn die Bits rein, daß Du über Mikrooptimierung nachdenken mußt?
Peter D. schrieb: > Mit wieviel MHz kommen denn die Bits rein, daß Du über Mikrooptimierung > nachdenken mußt? Wahrscheinlich ein klassischer Fall von "premature optimization"...
Gast
#5730217
Peter D. schrieb: > Mit wieviel MHz kommen denn die Bits rein, daß Du über Mikrooptimierung > nachdenken mußt? Ich glaube danach hat er gar nicht gefragt. Die Diskussion ist nur in diese Richtung abgedriftet, nachdem ich den Begriff "effizienteste Variante" einbrachte.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.