Interpolationsknas på Arduino

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Re: Interpolationsknas på Arduino

Inlägg av stekern »

superx skrev:Min erfarenhet är tyvärr att kompilatorerna är rätt korkade med sånt här. Läs här t.ex.
http://mekonik.wordpress.com/2009/03/18 ... plication/
Kompilatorutvecklingen går framåt, exemplet där verkar inte stämma längre.

Kod: Markera allt

#include <stdint.h>

uint32_t foo(uint16_t a, uint16_t b)
{
  return (uint32_t)a * (uint32_t)b;
}
ger:

Kod: Markera allt

$ avr-gcc -mmcu=atmega48 -O2 -S multest.c -o -
        .file   "multest.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__CCP__ = 0x34
__tmp_reg__ = 0
__zero_reg__ = 1
        .text
.global foo
        .type   foo, @function
foo:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
        movw r20,r24
        movw r18,r22
        rcall __umulhisi3
/* epilogue start */
        ret
        .size   foo, .-foo
Kollar man på libcallet som görs så ser __umulhisi3 ut såhär:

Kod: Markera allt

$ avr-objdump -d /usr/lib/gcc/avr/4.5.3/avr4/libgcc.a
.
.
00000000 <__umulhisi3>:
   0:   53 9f           mul     r21, r19
   2:   c0 01           movw    r24, r0
   4:   42 9f           mul     r20, r18
   6:   b0 01           movw    r22, r0
   8:   52 9f           mul     r21, r18
   a:   70 0d           add     r23, r0
   c:   81 1d           adc     r24, r1
   e:   11 24           eor     r1, r1
  10:   91 1d           adc     r25, r1
  12:   34 9f           mul     r19, r20
  14:   70 0d           add     r23, r0
  16:   81 1d           adc     r24, r1
  18:   11 24           eor     r1, r1
  1a:   91 1d           adc     r25, r1
  1c:   08 95           ret
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Re: Interpolationsknas på Arduino

Inlägg av stekern »

Sorry, jag såg nu att det var signed multiplikation i exemplet, men likvärdigt resultat uppnås
även där med ett rcall till __mulhisi3 istället.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Interpolationsknas på Arduino

Inlägg av bearing »

superx skrev:Testade lite med avr-gcc här.

Kod: Markera allt

uint16_t interp1(const uint8_t x, const uint8_t A, const uint8_t B, const uint8_t M)
{
  uint8_t AB = A-B;
  uint16_t V = B + (AB)*x/M;

  return V;
}
Ger 1 multiplikation

Kod: Markera allt

uint16_t interp2(const uint8_t x, const uint8_t A, const uint8_t B, const uint8_t M)
{
  uint16_t V = B + (A-B)*x/M;

  return V;
}
Ger 3 multiplikationer. Jag antar att det beror på att man i det övre fallet själv tar ansvar för att A-B inte slår runt. Går detta att utläsa av standarden?

EDIT: Ändrade AB från signed till unsigned
Det första exemplet måste ju göra en 8-bit multiplikation, så resultatet blir antagligen fel. Du behöver tala om för kompilatorn att högerledet ska utföras med 16 bitar.

Man måste väl göra 3 mul på en 8-bit processor ifall produkten och faktorerna är 16-bit.

Tror att avr-gcc går utanför standarden för att koden ska bli effektivare på en AVR.

EDIT: glöm detta inlägg. Nu fattar jag. Mul-instruktionen ger ju ett 16-bit resultat, och dina faktorer var 8 bit.
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Re: Interpolationsknas på Arduino

Inlägg av stekern »

superx skrev:Spännande exempel! Gäller att se upp när man blandar signed och unsigned verkar det som.

Testade lite med avr-gcc här.

Kod: Markera allt

uint16_t interp1(const uint8_t x, const uint8_t A, const uint8_t B, const uint8_t M)
{
  uint8_t AB = A-B;
  uint16_t V = B + (AB)*x/M;

  return V;
}
Ger 1 multiplikation

Kod: Markera allt

uint16_t interp2(const uint8_t x, const uint8_t A, const uint8_t B, const uint8_t M)
{
  uint16_t V = B + (A-B)*x/M;

  return V;
}
Ger 3 multiplikationer. Jag antar att det beror på att man i det övre fallet själv tar ansvar för att A-B inte slår runt. Går detta att utläsa av standarden?

EDIT: Ändrade AB från signed till unsigned
Förklaringen går mycket riktigt att hitta i standarden, närmare bestämt under kapitel 6.3.1.1 Boolean, characters, and integers paragraf 2:
"The following may be used in an expression wherever an int or unsigned int may
be used:
— An object or expression with an integer type whose integer conversion rank is less
than or equal to the rank of int and unsigned int.
— A bit-field of type _Bool, int, signed int, or unsigned int.
If an int can represent all values of the original type, the value is converted to an int;
otherwise, it is converted to an unsigned int. These are called the integer
promotions.48) All other types are unchanged by the integer promotions."


Som vi vet är en int 16 bitar i avr-gcc, så för det nedre exemplet ger detta oss att:
uint16_t V = B + ((int16_t)A-(int16_t)B)*x/M;
(int16_t)A-(int16_t)B kommer givetvis även de resultera i en int16_t

För det övre exemplet får vi:
uint16_t V = B + ((int16_t)AB)*x/M;

Men eftersom du talat om för kompilatorn att AB är trunkerat till uint8_t så har du gett den frihet att agera utifrån det.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Interpolationsknas på Arduino

Inlägg av bearing »

Kan man lägga till (uint8_t) eller liknande i det nedre exemplet, så att det utförs på samma sätt som det över exemplet?
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Re: Interpolationsknas på Arduino

Inlägg av stekern »

Ja, uint16_t V = B + ((uint8_t)(A-B))*x/M; ger ju givetvis samma slutresultat.
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: Interpolationsknas på Arduino

Inlägg av superx »

Heja stekern! det där hade jag inte koll på, men det förklarar ju ett och annat. Tack för att du tar dig tid!

Ja, helt enkelt är det iaf inte att skriva C-kod som kompilerar till det som man tänkt sig alla gånger.

Jag har egentligen mest haft problem av den här typen på plattformar med extra stor ackumulator och MAC-instruktioner (multiply-accumulate), där man gärna vill behålla alla delresultaten i ackumulatorn för att undvika rundningar.
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: Interpolationsknas på Arduino

Inlägg av Wedge »

Whohooo! Den förbättrade algoritmen drog ned tiden från 2,4 ms till 0,9 ms. Verkligen inte illa pinkat! :) I båda tiderna ingår lite annat enkel dataskyfflande som måste göras, så om vi gissar att interpolerandet gått från ca 2 till 0,5 ms ... 4 ggr snabbare!
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Interpolationsknas på Arduino

Inlägg av bearing »

Är det flera interpoleringar, eller tar funktionsanropet 0,5ms?
Det låter väldigt mycket isf.
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: Interpolationsknas på Arduino

Inlägg av Wedge »

Det är 16 RGB-dioders färg som ska beräknas. 48 interpoleringar totalt. Dvs storleksordningen 10 mikrosekunder per interpolering. Helt OK siffror, tycker jag.

EDIT: 10, inte 100 :doh:
Senast redigerad av Wedge 25 oktober 2012, 23:23:02, redigerad totalt 1 gång.
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Re: Interpolationsknas på Arduino

Inlägg av stekern »

superx skrev:Jag har egentligen mest haft problem av den här typen på plattformar med extra stor ackumulator och MAC-instruktioner (multiply-accumulate), där man gärna vill behålla alla delresultaten i ackumulatorn för att undvika rundningar.
Just DSP operationer har väl traditionellt varit lämnat åt att skrivas i assembler,
så att man får jobba lite extra för att få kompilatorerna att förstå vad man vill där kan jag mycket väl tänka mig.
Det blir säkert bättre på den fronten framöver, det samma gäller även vector instruktioner.
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: Interpolationsknas på Arduino

Inlägg av superx »

Wedge, är M variabel i ditt fall, och i så fall varför? Om den är känd vid kompileringen kan du säkert snabba upp den där uträkningen en del till.
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: Interpolationsknas på Arduino

Inlägg av Wedge »

M är variabel, ja. Den bestämmer hur lång en övergång från en färg till en annan ska vara. Sen räknar x ned från M till 0, ett steg för varje interrupt.
Skriv svar