Forum: Compiler & IDEs Multiplikation ist zu schnell...


von Marc Vollmer (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe mal ein Projekt angehängt (Zusammbau aus einigen gefundenen
Funktionen), im main mulitpliziere ich zwei doubles. Ich möchte nun
gerne wissen, wie lange diese Berechnung dauert. Also habe ich einen
Timer initialisiert und lese den Wert vor und nach der Berechnung aus.

Ich bekomme aber als Ergebnis, daß die Berechnung nur zwei Takte
benötigt, und dies kann bei einem 8 Bit Prozessor eigentlich nicht
sein. Wo ist denn mein Denkfehler?

-- Hier der relevante Ausschnitt --

int main(void)
{
    double a1=1.234, a2=2.756, a=0.0;
    int i;
    u08 data;
    u16 ticks1,ticks2;
    timer_init();                   /* init timer1 */
    UART_Init();                    /* Initialise UART */
    PRINT("Hello World !");
    EOL();
    for (;;) {  /* loop forever */
  ticks1 = TCNT1;   /* start measurement */
  //for(i=0;i<1000;i++)
    a = a1 * a2;
        ticks2 = TCNT1;   /* start measurement */
  UartPrintF("Ticks1? %u\r\n",ticks1);
  UartPrintF("Ticks2? %u\r\n",ticks2);
  UartPrintF("dTicks? %u us\r\n",(ticks2-ticks1)/4);
    }
}

von Matthias (Gast)


Lesenswert?

Hi

kann schon sein da der Compiler das wohl rausoptimiert. Da du
anscheinend den AVRGCC verwendest:

Schau dir mal mit

avr-objdump -t -h -S out.elf >out.lst (Dateinamen anpassen)

den ASM-Output an.

Matthias

von Marc Vollmer (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Matthias,

eigentlich sehe ich in der *.lst nichts, da keine ASMs hinter der
Berechung folgen. Siehe Zeile 280.

Wo sind denn dann die Befehle für die Berechnung?

Zumindest würde dies die schnelle Zeitmessung erklären, aber wo ist das
Ergebnis?

Sorry, aber ich blicke dieses ASM nicht sonderlich, dies scheint auch
der Grund zu sein, warum ich in C programmiere.

Gruss
Marc

von Stefan (Gast)


Lesenswert?

Du benutzt den Wert in A nie - also berechnet der Compiler ihn garnicht
erst.
Compiler sind faul - vor allem gcc. Das macht sie so menschlich ;-)

Definier mal a als volatile, d.h. gcc muss a berechnen, auch wenn er es
für unsinnig hält.

Aber auch dann kann es sein, dass gcc a1 und a2 als Konstanten erkennt
und die Multiplikation garnicht ausführt, man muss ziemlich tricksen,
um gcc sinnlos malochen zu lassen.

Stefan

von Marc Vollmer (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Stefan,

ich habe a mal über die Schnittstelle ausgegeben:

--
for(i=0;i<1;i++) {
    a = a1 * a2;
    a16 = (unsigned int)(a*1000);
}
ticks2 = TCNT1;   /* start measurement */
UartPrintF("a16? %u\r\n",a16);
--

Das Ergebnis ist richtig, und der Timer gibt mir raus, daß er nun 6
Takte brauch. Eigentlich immer noch zu wenig, da nun noch ein for
Anweisung und eine Umrechnung drin ist.

Gruss
Marc

von Stefan (Gast)


Lesenswert?

Hi Mark,

ich habe mal den asm-Code rausgeschnitte, der Deine Berechnung macht,
den anderen Kruscht habe ich weggelassen, damits klarer wird:

  47:mv_gcctest9.c ****       a = a1 * a2;
  48:mv_gcctest9.c ****       a16 = (unsigned
 ...
 158 0038 88E4          ldi r24,lo8(3400)
 159 003a 9DE0          ldi r25,hi8(3400)
 ...
 166 0048 0E94 0000     call UartPrintF


gcc lädt a (sprich: R24/R25) mit 3400 und ruft UartPrintF auf. Sprich:
Deine Berechnung wird wegoptimiert ...

Stefan

von Marc Vollmer (Gast)


Lesenswert?

Jetzt hab ich es verstanden, der Compiler hatte überhaupt keine
Veranlassung die Berechnung online auszuführen zu lassen, da sich der
Wert nicht änderte.

Nun habe ich die Routine etwas geändert:

double i;
for(i=0;i<1;i++) {
    a = a1 * i;
    a16 = (unsigned int)(a*1000);
}

Jetzt mußte der uP rechnen, da er das Ergebnis nicht vorbestimmen
konnte. Und siehe da, jetzt brauch die Berechnung 1068 Takte, bei einem
4 Mhz sind dies 267 us.  Schade eigentlich :-)

Danke an alle für die interessante Diskussion.

Gruss
Marc

von Stefan (Gast)


Lesenswert?

Ja, so habe ich mir das gedacht.

Wenn Du nach der Zeit optimieren willst, dann solltest Du als erstes
die Floats rausschmeissen. Meistens sind die garnicht nötig:

z.B. kannst Du statt 4,36V oft genausogut mit 4360mV rechnen, und schon
ist es eine "normale" Integer.

Je tiefer Du dich in Deine Zahlen reinversetzt, desto mehr Arbeit
kannst Du der CPU ersparen. Denke immer daran, dass Deine Zahlen im
Binärsystem gespeichert werden. Im Int-Bereich ist z.B *2 oder /2 ein
einfaches shiften, /256 bedeutet Weglassen des niederwertigsten Bytes
(shift rechts 8 Bits), dagegen /100 richtig viel Rechenarbeit.

Stefan

von Joerg Wunsch (Gast)


Lesenswert?

Warum schade?  Andere Microcontroller-Compiler haben gar kein
Gleitkomma erst...

Übrigens hängt die Ausführungszeit eine Multiplikation (und noch mehr
einer Divsion) nicht unerheblich von den Operanden ab.

von Peter D. (peda)


Lesenswert?

Auf einem Mega 8 dauert eine Multiplikation in C:

8 bit: 2 Zyklen
16 bit: 9 Zyklen
32 bit: 37 Zyklen


Peter

von Marc Vollmer (Gast)


Lesenswert?

Hallo Peter,

wie kommst Du auf diese Zyklen? Vorallem bei den 32 bit, gibt es
irgendwo eine Referenz.

Gruss
Marc

von Peter D. (peda)


Lesenswert?

@Marc,

ich habe einfach im Assemblerlisting die Zyklen gezählt:

<__mulsi3>:
mul     r22, r18
movw    r26, r0
mul     r23, r19
movw    r30, r0
mul     r24, r18
add     r30, r0
adc     r31, r1
mul     r22, r20
add     r30, r0
adc     r31, r1
mul     r25, r18
add     r31, r0
mul     r24, r19
add     r31, r0
mul     r23, r20
add     r31, r0
mul     r22, r21
add     r31, r0
eor     r25, r25
mul     r23, r18
add     r27, r0
adc     r30, r1
adc     r31, r25
mul     r22, r19
add     r27, r0
adc     r30, r1
adc     r31, r25


Peter

von Michael (Gast)


Lesenswert?

Wenn man in C programmiert, können floats auch von Vorteil sein: keine
fehlerträchtige Skalierung, um die Auflösung zu 'retten'. Wenn der
Compiler nicht die ATmega-MUL-Befehle unterstützt, kann die
float-Berechnung auch schneller sein als 32-bit Integer. Die Mantisse
ist ja nur 24-bit breit. Bei der Division kommt dies auf jeden Fall zum
tragen.

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.