Performance der 32Bit-HW Floating Point Einheit auf dem ARM11

#3479097
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.
#3479182
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
Angehängte Dateien:
#3479364
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.
#3479388
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. ;-)
#3479476
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!
#3480523
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?
#3480549
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.
Persönliche Seite #3480847
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 :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren