Forum: Compiler & IDEs Performance der 32Bit-HW Floating Point Einheit auf dem ARM11


von Jakob K. (jaykob)


Lesenswert?

Hi liebe Community,

aktuell programmiere ich auf einem Raspberry PI mit ARM11-Prozessor.
Laut Beschreibung besitzt dieser eine HW-FloatingPoint Unit, welche auch 
vom Betriebssystem (Wheezy Raspbian) unterstützt wird.

Nun zu meiner/meinem Frage/Problem:

Bei einer Zeitmessung der Float-Multiplikation stellte sich heraus, dass 
diese in etwa 50 Taktzylen benötigt. Dieser Wert erscheint mir doch sehr 
utopisch. Dies entspricht nach meinen Erwartungen eher dem Wert einer 
Soft-Float Multiplikation.

Ich habe darauf hin das Disassembly betrachtet um zu überprüfen ob 
wirklich eine HW-Float-Multiplikation ausgeführt wird.
Dorch tauchen Assembler Befehle wie FMULS oder FLDS auf, was auf eine 
HW-Multiplikation schließen lässt.

Habt ihr eine Idee ob ich irgendwas falsch mache oder ist die 
Multiplikation wirklich so langsam?
Das stellt leider ein großes Problem für mich da, da ich mehrere FFTs in 
"Echtzeit" verarbeiten und auswerten möchte.

Hier noch der Code, mit dem ich die Zeitmessung durchführe:
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <time.h>
4
#include <sys/time.h>
5
6
int main(void)
7
{
8
  struct timeval tim;
9
  int i;
10
  double t1,t2,c;
11
  float a= 1.000001, b = 1.00123;
12
    
13
  gettimeofday(&tim, NULL);
14
    t1=tim.tv_sec+(tim.tv_usec/1000000.0);
15
    
16
  for (i=0;i<1e6;i++)
17
      a *= b;
18
    
19
  gettimeofday(&tim,NULL);
20
    t2=tim.tv_sec+(tim.tv_usec/1000000.0);
21
22
    c = t2-t1;
23
    printf("%.6lf - %.6lf = %.6lf\n",t2,t1,c);
24
    
25
  return(0);
26
}

Kompiliert habe ich das ganze mit folgendem Befehl:

1
 
2
3
g++ -Wall -fPIC -mfloat-abi=hard -mfpu=vfp -mcpu=arm1176jzf-s timeMeasure.cpp


Vielen Dank für eure Mühe.

von (prx) A. K. (prx)


Lesenswert?

Jakob K. schrieb:
> for (i=0;i<1e6;i++)

Da steckt mit etwas Glück in jeder Iteration eine 
Fliesskommakonvertierung drin. 1e6 ist keine Integer.

Falls das nicht ändert: Der Assembler-Code könnte helfen.

Zu erwarten wären 8 Takte für FMUL, laut Doku.

von Jakob K. (jaykob)


Angehängte Dateien:

Lesenswert?

A. K. schrieb

> Da steckt mit etwas Glück in jeder Iteration eine
> Fliesskommakonvertierung drin. 1e6 ist keine Integer.

Wenn ich zum Vergleich eine Integer-Variable verwende, veringert sich 
die Anzahl auf etwa 30 Takte.

Wo hast du denn die Information mit den 8 Takten her? Ist dieser Wert 
nur für die FMUL Anweisung oder die gesamte Multiplikation?
Die Multiplikaiton in der Schleife sieht folgendermaßen aus:
1
flds  s14, [fp, #-12]
2
flds  s15, [fp, #-20]
3
fmuls  s15, s14, s15

Im Anhang ist der kompette Assembler-Code


Vielen Dank für die Tipps

von (prx) A. K. (prx)


Lesenswert?

Jakob K. schrieb:
> Wo hast du denn die Information mit den 8 Takten her?

Wenn dein -mcpu stimmt, dann aus Seite 683 von:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf

> Ist dieser Wert nur für die FMUL Anweisung

Ja. Ich ging allerdings von eingeschalteter Optimierung aus. Die fehlt 
hier, so dass die Variablen nicht in Registern liegen, sondern im 
Speicher. Das macht viel aus.

von (prx) A. K. (prx)


Lesenswert?

Jakob K. schrieb:
> Wenn ich zum Vergleich eine Integer-Variable verwende, veringert sich
> die Anzahl auf etwa 30 Takte.

Für diesen Code sind 30 Takte eigentlich ganz ok:
1
.L3:
2
  flds  s14, [fp, #-12]   ; a *= b;
3
  flds  s15, [fp, #-20]
4
  fmuls  s15, s14, s15
5
  fsts  s15, [fp, #-12]
6
7
  ldr  r3, [fp, #-8]      ; i++
8
  add  r3, r3, #1
9
  str  r3, [fp, #-8]
10
.L2:
11
  ldr  r2, [fp, #-8]      ; Schleife in aller Umständlichkeit
12
  ldr  r3, [fp, #-16]
13
  cmp  r2, r3
14
  movge  r3, #0
15
  movlt  r3, #1
16
  uxtb  r3, r3
17
  cmp  r3, #0
18
  bne  .L3

Mit Optimierung wird er entweder besser, oder - wahrscheinlicher - 
verschwindet mangels verwendetem Ergebnis ganz. ;-)

von Jakob K. (jaykob)


Lesenswert?

A. K. schrieb:

> Mit Optimierung wird er entweder besser, oder - wahrscheinlicher -
> verschwindet mangels verwendetem Ergebnis ganz. ;-)

Da bei der Optimierung die Schleife ganz raus fällt, habe ich die 
Optimierung eben abgeschaltet.


Danke für den Link zum Datenblatt, hätte ich mal selber suchen sollen ;)

Berücksichtigt man neben der Multiplikation noch das Lesen/Schreiben der 
Werte aus dem Speicher, kommt man schon auf ca. 20 Takte.



Ich bedanke mich für die großartige und schnelle Hilfe!

von (prx) A. K. (prx)


Lesenswert?

Jakob K. schrieb:
> Da bei der Optimierung die Schleife ganz raus fällt, habe ich die
> Optimierung eben abgeschaltet.

Es hätte ausgereicht, a im printf mit auszugeben.

von (prx) A. K. (prx)


Lesenswert?

Jakob K. schrieb:
> Berücksichtigt man neben der Multiplikation noch das Lesen/Schreiben der
> Werte aus dem Speicher, kommt man schon auf ca. 20 Takte.

Da die VFP-Unit gepipelined ist und die FLD Befehle nicht voneinander 
abhängig sind brauchen die zusammen nur 5 Takte. Also FLD+FLD+FMUL+FST = 
1+4+8+1=14.

von Rolf Magnus (Gast)


Lesenswert?

Jakob K. schrieb:
> Da bei der Optimierung die Schleife ganz raus fällt, habe ich die
> Optimierung eben abgeschaltet.

Ohne Optimierungen brauchst du dich allerdings auch nicht zu wundern, 
daß die Laufzeit sehr weit vom Optimum entfernt liegt.

von Jakob K. (jaykob)


Lesenswert?

So ich habe zur Vervollständigung noch mal eine Messung mit Optimierung 
(und Ausgabe des Parameters) gemacht, und es ergibt sich der zuvor 
erwähnte Wert von etwa 14 Zyklen.

A. K. schrieb:
>
> Da die VFP-Unit gepipelined ist und die FLD Befehle nicht voneinander
> abhängig sind brauchen die zusammen nur 5 Takte. Also FLD+FLD+FMUL+FST =
> 1+4+8+1=14.

Ok das hilft mir schon weiter, dann lässt sich zumindest ein kleiner 
Teil parallelisieren. Ich hätte dazu noch ne kleine Frage. Entnehme ich 
dem Handbuch des Prozessors (Seite 681) richtig, dass die CPU max. 3 
Anweisungen parallel abarbeiten kann?

von (prx) A. K. (prx)


Lesenswert?

Jakob K. schrieb:
> Entnehme ich
> dem Handbuch des Prozessors (Seite 681) richtig, dass die CPU max. 3
> Anweisungen parallel abarbeiten kann?

Je nach konkretem Befehlsmix scheint die VFP11 in der Lage zu sein, pro 
Takt einen VFP-Befehl zu starten, auch wenn der einzelne davon 8 Takte 
dauert. Wieviele Befehle das dann parallel sind bzw. im Idealfall sein 
könnten, ist etwas Ansichtssache.

Lies dir das lieber mal vor vorne durch, also ab S.612. So ganz trivial 
ist die VFP11-Unit nicht.

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Die VFP des ARM11 implementiert keine SIMD Vektor Verabeitung wie, z.B. 
NEON. Vielmehr gibt es Befehle die dazu führen, dass VFP Operationen 
eigenständig in Schleifen über mehrere Register (Vektorelemente) 
ausgeführt werden. Kein mir bekannter Compiler wird diese Befehle 
automatisch erzeugen. Bestenfalls bekommst Du irgendwo eine Lib (z.B. 
OpenMAX), die diese Funktionalität intern verwendet. Oder Du musst 
selber ran :)

von (prx) A. K. (prx)


Lesenswert?

Ja, so hat sich mir das auch dargestellt. Der TO hat aber wahrscheinlich 
erst einmal genug damit zu tun, die Arbeitsweise der Skalaroperationen 
zu verstehen und einzuschätzen. ;-)

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.