Forum: Compiler & IDEs Multiplikationen = Performancefresser?


von Detlef (Gast)


Lesenswert?

Hi

habe leider einige solcher Multiplikationen auszuführen:

for (a=0;a<max;a++){
tmp.data[a*3]=0;
tmp.data[a*3+1]=0;
tmp.data[a*3+2]=0;
}

Ich frage mich ob der Prozessor durch solche Sachen gebremst wird.
Mit 2 Multiplizieren / dividieren lässt sich ja durch Bit links/rechts 
verschiebung verschnellern. Aber bei 3 ?

von Stock H. (winkelmesser)


Lesenswert?

Machst du noch was anderes mit a?

ansonsten : for(a=0;a<max;a=a3){...}
oder die Felder per memset() setzen...

von Ulrich (Gast)


Lesenswert?

Der Code benötigt bei mir 14Bytes.
habe ich in ein vorhandenes projekt eingefügt....

von johnny.m (Gast)


Lesenswert?

Was hast Du denn für einen Prozessor? Viele Mikrocontroller haben einen 
Hardware-Multiplier. Solange Du ganzzahlig multiplizierst, sollte das 
nicht großartig lange dauern. Bei CPUs ohne Hardware-Multiplier sieht 
das anders aus. Aber eine Multiplikation mit 3 ist auch ohne 
HW-Multiplier kein Problem (a*3 = a+a+a)...

von Detlef (Gast)


Lesenswert?

ok, ich glaube einen HW Multi zu haben

amax ist übrigens auch nur 8

also max 3*8

von A.K. (Gast)


Lesenswert?

Ein besserer Compiler kriegt selber spitz, dass er dafür keine 
Multiplikation benötigt (strength reduction).

von Oliver (Gast)


Lesenswert?

"Ich frage mich ob der Prozessor durch solche Sachen gebremst wird."

Nein. Der läuft immer gleich schnell.
Und wenn deine Anwendung in allen Bereichen wegen der paar 
Integer-Multiplikationen zu langsam läuft, brauchst du entweder einen 
schnelleren Quarz, oder einen schnelleren Prozessor. Kurze 
Interruptroutinen lassen sich auch von Hand optimieren. Ausserdem wird 
der Compiler mit eingeschalteter Optimierung in deinem Beispiel das a*3 
nur einmal berechnen. So schlau ist der dann doch.

Oliver

von Ulrich (Gast)


Lesenswert?

10:       tmpdata[a*3]=0;
+00000035:   8210        STD     Z+0,R1           Store indirect with 
displacement
11:       tmpdata[a*3+1]=0;
+00000036:   8211        STD     Z+1,R1           Store indirect with 
displacement
12:       tmpdata[a*3+2]=0;
+00000037:   8212        STD     Z+2,R1           Store indirect with 
displacement
9:        for (a=0;a<10;a++){
+00000038:   5081        SUBI    R24,0x01         Subtract immediate
+00000039:   9633        ADIW    R30,0x03         Add immediate to word
+0000003A:   FF87        SBRS    R24,7            Skip if bit in 
register set
+0000003B:   CFF9        RJMP    PC-0x0006        Relative jump
17:       }

von Gast (Gast)


Lesenswert?

fehlt da jetzt nicht der Teil mit der Berechnung des Wertes für Z? Das 
wäre ja das interessante, oder nicht?

von Karl H. (kbuchegg)


Lesenswert?

Gast wrote:
> fehlt da jetzt nicht der Teil mit der Berechnung des Wertes für Z? Das
> wäre ja das interessante, oder nicht?

Der springende Punkt ist, dass in der Berechnunug von Z keine
Multiplikation mit 3 mehr vorkommt.

Der Compiler ist ein ganz ein schlauer.
Er hat gemerkt, dass er in der Schleife

for (a=0;a<10;a++){

das Z Register einfach nur um 3 erhöhen muss

9633        ADIW    R30,0x03

um die Multiplikation einzusparen.
Aus der Schleife

for (a=0;a<10;a++){
  tmpdata[a*3]=0;
  tmpdata[a*3+1]=0;
  tmpdata[a*3+2]=0;
}

macht der Compiler
                           Z_Pointer = Basispointer tempdata[0]
                           a = 9

  STD     Z+0,R1           *(Z_Pointer) = 0
  STD     Z+1,R1           *(Z_Pointer+1) = 0
  STD     Z+2,R1           *(Z_Pointer+2) = 0
  SUBI    R24,0x01         a = a - 1
  ADIW    R30,0x03         Z_Pointer = Z_Pointer + 3
  SBRS    R24,7            Unterlauf bei a = a - 1?
  RJMP    PC-0x0006        Nein -> nächster Durchgang

(Die Initialisierung des Z Registers mit der Basisadresse von
tmpdata, sowie die Vorbelegung von R24 mit 9 ist nicht gezeigt.
Du kannst dir aber denken wie die aussieht).
Sei ehrlich: besser hättest du das auch nicht hingekriegt.

von Gast (Gast)


Lesenswert?

ahhh... er hat quasi sowas wie:

Index = 0;
for(a=9;a>=0; a--)
{
  tmpdata[Index] = 0;
  tmpdata[Index+1] = 0;
  tmpdata[Index+2] = 0;

  Index += 3;
}

draus gemacht?
Das is ja geschickt. Macht er das immer oder nur bei eingeschalteten 
Optimierungen?

Gast.

von Karl H. (kbuchegg)


Lesenswert?

Gast wrote:
> ahhh... er hat quasi sowas wie:
>
> Index = 0;
> for(a=9;a>=0; a--)
> {
>   tmpdata[Index] = 0;
>   tmpdata[Index+1] = 0;
>   tmpdata[Index+2] = 0;
>
>   Index += 3;
> }
>
> draus gemacht?

So ähnlich

  unsigned char* data = tmpdata;
  for(a=9;a>=0; a--)
  {
    *data = 0;
    *(data + 1) = 0;
    *(data + 2) = 0;
    data += 3;
  }

Für die Arrayindizierung bräuchte er ja wieder eine
Multiplikation. Aber du hast das Prinzip schon richtig
erkannt :-)

> Das is ja geschickt.

Gelle. So ein Compiler hat heutzutage schon eine Menge
Optimierungen drauf. Manchmal haut er gcc-Optimizer auch
ein bischen daneben. Das liegt aber daran, dass der gcc
nicht nur für µC gebaut ist, sondern eine breite Palette
von Prozessoren, bis hin zu Grossrechnern abdecken muss.
Und dann gibt es noch den C Standard, der manchmal eine
Optimierung, die ein Assemblerprogrammierer machen würde,
verhindert.

> Macht er das immer oder nur bei eingeschalteten
> Optimierungen?

Die muessen schon eingeschaltet sein.
Der Grund dafür ist: Wenn du so eine Optimierung im Debugger
duchsteppst, dann erkennst du den Programmfluss nicht mehr
wieder: Zeilen werden in seltsamen Reihenfolgen ausgeführt,
Variablen ändern ihren Wert nicht so, wie man es aus dem
C-Quellcode erwarten würde, etc.
Beim Debuggen wäre sowas verwirrend, also sollte man zum
Debuggen eine Möglichkeit haben, Optimierungen gänzlich
abzuschalten.

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
Noch kein Account? Hier anmelden.