Forum: Mikrocontroller und Digitale Elektronik Festkommamultiplikation mit ARM


von harald (Gast)


Lesenswert?

Ich habe eine Frage.

Hintergrund:

Mit einem ARM7TDMI berechne ich einiges (mit Additionen und 
Multiplikationen) und nehme dazu Fließkommazahlen (32 bit) bzw 
Festkommazahlen (32bit).

Mein ARM hat keine FPU und deshalb ist Floatingpoint relativ langsam.
Falls ich die Berechnungen mit Festkommazahlen implementiere sind diese 
"nur" 2 mal so schnell.

Ich dachte ursprünglich, dass Festkommaimplementierungen sehr viel 
schneller sind. An den Additionen kann es nicht liegen, da diese 
"gleich" sind wie normale Integer.

Bei den Multiplikationen verwende ich als Zwischenergebnis eine 64 bit 
Zahl und schiebe anschließend zurück.

#define fmult(A,B) (long)(((long long)A * (long long)B) >> KOMMASTELLEN)

Zur eigentlichen Frage:
Wie kann ich die Multiplikation verbessern?

von harald (Gast)


Lesenswert?

nachdenk

von (prx) A. K. (prx)


Lesenswert?

Festkommamultiplikation ist ganz praktisch, wenn man Hardware-Support 
für ganzzahlige Multiplikation hat. Bis rauf zu 32x32=64bit hat ARM das 
in Form eines Befehls, aber mit 64x64=64bit kann ARM nicht dienen und 
damit wird es komplizierter. Klüger wär's wohl, diesen 32x32=64bit 
Befehl auch zu nutzen, wenn man sowieso nicht mehr als den braucht.

Im GCC kann man das beispielsweise recht wirkungsvoll mit
1
inline long fmult(long x, long y)
2
{
3
  long long r;
4
  asm ("smull %0,%H0,%1,%2" : "=&r"(r) : "r"(x), "r"(y));
5
  return r >> KOMMASTELLEN;
6
}

von (prx) A. K. (prx)


Lesenswert?

Bei 64x64bit hast du eine Laufzeitfunktion an der Backe, die nicht viel 
einfacher aussieht als die einer Fliesskommamultiplikation.

von harald (Gast)


Lesenswert?

Vielen Dank A.K.! Es ist ja super, dass es dafür einen extra Befehl 
gibt.

Ich habe gesehen, es gibt auch den  "smlal" Befehl, könntest du mir kurz 
skizzieren, wie ich den mit dem "asm" benutzen kann?

von (prx) A. K. (prx)


Lesenswert?

static inline long long
smull(long x, long y)
{
  long long r;
  asm ("smull %0,%H0,%1,%2" : "=&r"(r) : "r"(x), "r"(y));
  return r;
}

static inline long long
smlal(long x, long y, long long sum)
{
  asm ("smlal %0,%H0,%1,%2" : "+r"(sum) : "r"(x), "r"(y));
  return sum;
}

von harald (Gast)


Lesenswert?

Super, vielen Dank. Ich probiere es morgen aus und schaue ob es 
schneller wird.

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.