Jak jsem si nabehnul aneb double v pacalu na AVR
Jaroslav Buchta
jaroslav.buchta na hascomp.cz
Úterý Červenec 22 09:07:25 CEST 2014
OK, tak jednotlive operace mi vychazeji takto, optimalizace je O1
Rekl bych, ze mezi pouzitim int_32t a float neni propastny rozdil,
nejvetsi rozdil je logicky u scitani
volatile int32_t ri;
volatile float rf;
int main(void)
{
volatile int32_t i = 14;
volatile float f = 12.3;
volatile int32_t ki = 1234;
volatile float kf = 3.1415926;
ri = i + ki; //27 cyklu
ri = i * ki; //73 cyklu
ri = ri / ki; //638 cyklu
rf = f + kf; //128 cyklu
rf = f * kf; //154 cyklu
rf = rf / kf; //651 cyklu
Dne 22. 7. 2014 7:19, Jan Waclawek napsal(a):
>> Skoro uz jsem chtel udelat test
>> rychlosti ale zrovna jsem nemel po ruce AVR...
> Na to predsa nepotrebujete AVR, staci (ba dokonca je lepsi) simulator.
>
> Vid dole.
>
> Ta celociselna varianta je asi 4060 cyklov, ta s double asi 27000 s
> WinAVR20100110 (t.j. avr-gcc 4.3.3). A to som sa prilis nenamahal
> optimalizovat... ;-)
>
> Schvalne som nepouzival type punning, aby sa to dalo 1:1 prepisat do
> Pascalu - pri volaniach treba pouzit referencie miesto pointrov, ->
> nahradit ^., poupravovat definicie, nemalo by to dat privela roboty.
>
> Na druhej strane som v tej variante s double, co som vykopiroval z appnote,
> musel upravit dva riadky, inak to vracia dvojnasobny vysledok - nechapem
> preco to tak napisal ten co to napisal.
>
> Mozete skusit ten ARM, ked uz ho mate poruke :-)
>
> wek
>
>
>
> #include <stdint.h>
>
> #define SHR >>
> #define SHL <<
> #define OR |
> #define AND &
>
> // #define DEBUG
> #ifdef DEBUG
> typedef union {
> struct __attribute__((packed)) {
> uint16_t h0;
> uint16_t h1;
> uint16_t h2;
> uint16_t h3;
> };
> uint64_t f;
> } h64_t;
> #else
> typedef struct __attribute__((packed)) {
> uint16_t h0;
> uint16_t h1;
> uint16_t h2;
> uint16_t h3;
> } h64_t;
> #endif
>
> void umul16_32(h64_t * c, uint16_t b, uint32_t a) {
> uint32_t t;
> t = (a AND 0xFFFF) * b;
> c->h0 = t AND 0xFFFF;
> c->h1 = t SHR 16;
> t = (a SHR 16) * b;
> c->h2 = t SHR 16;
> t = (t AND 0xFFFF) + c->h1;
> c->h1 = t AND 0xFFFF;
> t = (t SHR 16) + c->h2;
> c->h2 = t AND 0xFFFF;
> c->h3 = t SHR 16; // this is always 0 anyway...
> }
>
> void umul32_64(h64_t * c, uint32_t b, h64_t * a) {
> h64_t t;
> uint32_t tl;
>
> umul16_32(&t, a->h0, b);
> c->h0 = t.h0; c->h1 = t.h1; c->h2 = t.h2; c->h3 = t.h3;
> umul16_32(&t, a->h1, b);
> tl = (uint32_t)c->h1 + t.h0;
> c->h1 = tl AND 0xFFFF;
> tl = (tl SHR 16) + c->h2 + t.h1;
> c->h2 = tl AND 0xFFFF;
> tl = (tl SHR 16) + c->h3 + t.h2;
> c->h3 = tl AND 0xFFFF;
> umul16_32(&t, a->h2, b);
> tl = (uint32_t)c->h2 + t.h0;
> c->h2 = tl AND 0xFFFF;
> tl = (tl SHR 16) + c->h3 + t.h1;
> c->h3 = tl AND 0xFFFF;
> umul16_32(&t, a->h2, b);
> tl = (uint32_t)c->h3 + t.h0;
> c->h3 = tl AND 0xFFFF;
> }
>
> void shr64(h64_t * c, uint8_t s) {
> if (s < 16) {
> c->h0 = (c->h0 SHR s) OR (c->h1 SHL (16 - s));
> c->h1 = (c->h1 SHR s) OR (c->h2 SHL (16 - s));
> c->h2 = (c->h2 SHR s) OR (c->h3 SHL (16 - s));
> c->h3 = (c->h3 SHR s);
> } else { // we won't need s = 16 nor s > 32
> s = s - 16;
> c->h0 = (c->h1 SHR s) OR (c->h2 SHL (16 - s));
> c->h1 = (c->h2 SHR s) OR (c->h3 SHL (16 - s));
> c->h2 = (c->h3 SHR s);
> c->h3 = 0;
> }
> }
>
> void neg64(h64_t * c) {
> c->h0 = ~c->h0 + 1;
> c->h1 = ~c->h1;
> if (c->h0 == 0) c->h1++;
> c->h2 = ~c->h2;
> if (c->h1 == 0) c->h2++;
> c->h3 = ~c->h3;
> if (c->h2 == 0) c->h3++;
> }
>
> void add64(h64_t * c, h64_t * b, h64_t * a) {
> uint32_t t;
> t = a->h0 + b->h0;
> c->h0 = t AND 0xFFFF;
> t = (t SHR 16) + a->h1 + b->h1;
> c->h1 = t AND 0xFFFF;
> t = (t SHR 16) + a->h2 + b->h2;
> c->h2 = t AND 0xFFFF;
> t = (t SHR 16) + a->h3 + b->h3;
> c->h3 = t AND 0xFFFF;
> }
>
>
> uint32_t calcPressure(uint32_t d1, uint32_t d2, uint16_t c1, uint16_t c2,
> uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6)
> __attribute__((noinline));
> uint32_t calcPressure(uint32_t d1, uint32_t d2, uint16_t c1, uint16_t c2,
> uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6) {
> uint32_t temp32, dt;
> _Bool minus;
> h64_t temp64, off, sens, p;
>
> temp32 = (uint32_t)c5 SHL 8;
> minus = (temp32 > d2);
> if (minus) {
> dt = temp32 - d2;
> } else {
> dt = d2 - temp32;
> }
>
> umul16_32(&off, c4, dt);
> shr64(&off, 7);
> if (minus) {
> neg64(&off);
> }
> temp64.h0 = 0; temp64.h1 = c2; temp64.h2 = 0; temp64.h3 = 0;
> add64(&off, &off, &temp64);
>
> umul16_32(&sens, c3, dt);
> shr64(&sens, 8);
> if (minus) {
> neg64(&sens);
> }
> temp32 = (uint32_t)c1 SHL 15;
> temp64.h0 = temp32 AND 0xFFFF; temp64.h1 = temp32 SHR 16; temp64.h2 = 0;
> temp64.h3 = 0;
> add64(&sens, &sens, &temp64);
>
> minus = ((sens.h3 AND 0x8000) != 0);
> if (minus) neg64(&sens);
> umul32_64(&p, d1, &sens);
> if (minus) neg64(&p);
> shr64(&p, 21);
> neg64(&off);
> add64(&p, &p, &off);
> shr64(&p,15);
>
> return ((uint32_t)p.h1 SHL 16) + p.h0;
> }
>
> #include <math.h>
>
> double calcPressure2(uint32_t d1, uint32_t d2, uint16_t c1, uint16_t c2,
> uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6)
> __attribute__((noinline));
> double calcPressure2(uint32_t d1, uint32_t d2, uint16_t c1, uint16_t c2,
> uint16_t c3, uint16_t c4, uint16_t c5, uint16_t c6) {
> double P; // compensated pressure value
> // double T; // compensated temperature value
> double dT; // difference between actual and measured temperature
> double OFF; // offset at actual temperature
> double SENS; // sensitivity at actual temperature
>
> // calcualte 1st order pressure and temperature (MS5607 1st order
> algorithm)
> dT=d2-c5*pow(2,8);
> // OFF=(double)c2*pow(2,17)+dT*c4/pow(2,6);
> OFF=(double)c2*pow(2,16)+dT*c4/pow(2,7);
> // SENS=c1*pow(2,16)+dT*c3/pow(2,7);
> SENS=c1*pow(2,15)+dT*c3/pow(2,8);
> // T=(2000+(dT*c6)/pow(2,23))/100;
> P=(((d1*SENS)/pow(2,21)-OFF)/pow(2,15))/100;
> return P;
> }
>
>
> volatile uint32_t p;
> volatile double pp;
> int main(void) {
> p = calcPressure(9085466, 8569150, 40127, 36924, 23317, 23282, 33464,
> 28312);
> __asm("nop");
> pp = calcPressure2(9085466, 8569150, 40127, 36924, 23317, 23282, 33464,
> 28312);
> __asm("nop");
> while(1);
> }
>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com
Další informace o konferenci Hw-list