int16 FIX_MPY(int16 a, int16 b) { // shift right one less bit int32 c = ((int32)a * (int32)b) >> 14; // last bit shifted out = rounding-bit b = c & 0x01; // last shift + rounding bit a = (c >> 1) + b; return a; } Gibts da Optimierungspotential? Die Routine wird sehr oft (16384 mal pro Berechnung) aufgerufen, wenn man da noch was machen könnte, ich bin in Zeitnot :-) Ist für einen M16, und auf die Rundung kann ich nicht verzichten. Ich sehe nichts mehr.
Hallo, du könntest die Multiplikation vom HW-Multiplizierer ausführen lassen. Normalerweise sollte sich unter den intrinsics was finden lassen. Dann würde ich wahrscheinlich zwei mal nach links schieben und das Hiword nehmen. Mir ist z.B. beim IAR Compiler mal aufgefallen, dass der Compiler wirklich 14 mal schiebt in solchen Fällen (hängt wahrscheinlich von der Optimierungsstufe ab). Zwei mal schieben und dann ein mov.w ist da schon etwas schneller. Kannst Du die Funktion evtl. als inline Funktion verwenden? Viele Grüße, Ralf
;## # FUNCTION FIX_MPY ;## # FRAME AUTO ( __PAD11) size 1, offset -1 ;## # REGISTER ARG ( a) size 2, REGISTER R1 ;## # REGISTER ARG ( b) size 2, REGISTER R2 ;## # ARG Size(0) Auto Size(1) Context Size(5) ._type 307,'x',269,2 ._type 307,'m','a',0,269 ._type 307,'m','b',0,269 ._func 'FIX_MPY','G',1,307,$FIX_MPY,0 ._inspect 'F', 's', "FIX_MPY", "$FIX_MPY", 'G', 6 .align ._line 303 ;## # C_SRC : { .glb $FIX_MPY $FIX_MPY: enter #01H ._block ._var 'a','A',269,0 ._var 'b','A',269,0 ._var 'c','A',292,0 ._line 305 ;## # C_SRC : int32 c = ((int32)a * (int32)b) >> 14; ._block ._var 'a','R',269,6 ._var 'b','R',269,7 mul.w R2,R1 ; b ._eblock sha.l #-8H,R3R1 sha.l #-6,R3R1 ._line 307 ;## # C_SRC : b = c & 0x01; mov.w R1,R0 and.w #0001H,R0 ; b ._block ._var 'b','R',269,5 ._line 309 ;## # C_SRC : a = (c >> 1) + b; sha.l #-1,R3R1 add.w R1,R0 ; a ._eblock ._block ._var 'a','R',269,5 ._line 312 ;## # C_SRC : return a; ._eblock exitd das der Auszug aus dem listing. Scheint genauso gemacht, wie du vorgeschlagen hast, schade. Trotzdem vielen Dank.
What is the exact purpose of your code? Knowing that can help to optimise. By shifting right by 14 places, you are throwing away a lot of information. Maybe you can find a way to figure out how to not calculate those bits in the first place. As far as I understand, even many hardware multipliers have a variable execution time that increases with the number of non-zero bits. The following code is a little simpler and should be equivalent to yours: int16 FIX_MPY(int16 a, int16 b) { // shift right one less bit int32 c = ((int32)a * (int32)b) >> 14; // round it return ((c + 1) >> 1); }
Thanks for the idea! int16 FIX_MPY(int16 a, int16 b) { int32 c = ((int32)a * (int32)b + (1<<14)) >> 15; return c; } Irgendwie geht immer noch was :-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.