Sari la conținut
ELFORUM - Forumul electronistilor

AVR Studio este foarte incet la calcule cu numere tip float


simplex

Postări Recomandate

Compilatorul care merge cu AVR Studio 4.18, 4.19 genereaza un algoritm in limbaj de asamblare foarte incet pentru calcule cu numere float

 

Ce setari trebuie sa fac pentru a accelera inmultirile de numere in virgula mobila.

 

Compilator AVR Studio 4.18

uint16_t = uint8_t * uint8_t -> 10 Clock Cycles - REPEDE

uint32_t = uint16_t * uint16_t -> 29 Clock Cycles - ACCEPTABIL

float = float * float -> 2076 Clock Cycles - FOARTE INCET

(a se vedea programul atasat)

 

Este greu de crezut ca sunt necesari 2076 tacti pentru a efectua un produs float = float * float in timp ce doua cantitati intregi intre 0 si 65535 (uint32_t = uint16_t * uint16_t) sunt inmultite in doar 29 cicli.

 

Programul folosit pentru testari este urmatorul:

 

 

#include <avr/io.h>uint8_t i, s;volatile uint8_t a8, b8;volatile uint8_t p16;volatile uint16_t a16, b16;volatile uint32_t p32;volatile float af, bf;volatile float pf;int main(void){   a8=143;   b8=249;   a16=37453;   b16=58274;   af=374.367893;   bf=58274.8982;      for (i=1;i<5;i++)   {    p16 = a8 * b8; // CC -> 308    p32 = a16 * b16; // CC -> 318    pf = af * bf; // CC -> 347    s = 1; // CC -> 2423   }return 1;}
Link spre comentariu
  • Răspunsuri 12
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • simplex

    7

  • godFather89

    4

  • nr4

    2

Top autori în acest subiect

Verifica asta:

You are not linking in the math library from AVR-LibC. GCC has a library that is used for floating point operations, but it is not optimized for the AVR, and so it generates big code, or it could be incorrect. This can happen even when you are not using any floating point math functions from the Standard C library, but you are just doing floating point math operations.When you link in the math library from AVR-LibC, those routines get replaced by hand-optimized AVR assembly and it produces much smaller code.

Link-uit math-ul si cu o simulare fara optimizari (oricum nu prea are ce optimiza) sunt necesari 1839 ciclii pentru o inmultire. Mi se pare destul de normal. Nu are instructiuni pentru operatii cu virgula mobila.

Link spre comentariu

Link-uit math-ul si cu o simulare fara optimizari (oricum nu prea are ce optimiza) sunt necesari 1839 ciclii pentru o inmultire. Mi se pare destul de normal. Nu are instructiuni pentru operatii cu virgula mobila.

Inmultirea a doua numere tip float este de fapt inmultirea a doi intregi (pe 32 biti de ex.) si adunarea altor doi (pe 8 biti de regula) deoarece orice cantitate cu virgula se poate scrie ca:

float = intreg cu semn*10^(intreg cu semn)

Din programul de mai jos rezulta clar ca numerele tip float af=45343454E-34, bf=-27474534E21 sunt inmultite in 2513 cicli, in timp ce facind un artificiu si lucrind separat cu mantisele si exponentii lui af si bf rezultatul final apare dupa doar 102 tacti adica de 24 ori mai repede, lucru care nu este de neglijat.

 

Foarte sincer, impresia mea este ca uitam sa facem vreo setare in compilator sau in alta parte undeva prin AVR Studio si asta este cauza pentru care operatiile float * float sunt asa incete sau poate compilatorul nu este bun.

 

#include <avr/io.h>#include <math.h>uint8_t i; volatile uint8_t q;volatile int8_t ae8, be8;volatile int16_t se16;volatile int32_t am32, bm32;volatile int64_t pm64;volatile float af, bf;volatile long pf;int main(void) {   ae8=-34;   be8=21;   am32=45343454;   bm32=-27474534;   af=45343454E-34;   bf=-27474534E21;      for (i=1;i<5;i++)   {    pm64 = am32 * bm32; // CC -> 393    se16 = ae8 + be8; // CC -> 479     pf= af * bf; // CC -> 495    q = 1; // CC -> 3008   }return 1;}
Link spre comentariu

Problema pe care nu o intelegi se rezuma la studiul arhitecturilor de microprocesoare."Artificiile" ce pentru creierul uman par logice, nu par la fel de logice pentru orice unitate ALU.Asa cum ti-a spus si godFather89, microcontroler-ul nu contine o unitate FPU sau macar ceva dedicat in acest sens, ca prin urmare compilatorul "este foarte bun".Recomand sa studiezi totusi ce face un compilator caci golurile sunt mari, probabil si din lipsa de documentare tehnica asupra microcontrolerelor atmega sau ce simulezi.

Link spre comentariu

Recomand sa studiezi totusi ce face un compilator caci golurile sunt mari, probabil si din lipsa de documentare tehnica asupra microcontrolerelor atmega sau ce simulezi.

1) Raspunsul nu este folositor. Alte ramarci nu mai fac deoarece as jigni.2) Keil uVision4 pentru 8051 genereaza cod assembler care face inmultiri float * float in mult mai putini tacti (de vreo 10 ori) decit codul echivalent generat de AVR Studio pentru procesoare AVR.Atit 8051 cit si AVR nu au Floating Point Hardware Multipliers, nu au instructiuni assembler dedicate inmultirii numerelor in virgula mobila, si cu toate astea 8051 este aparent de vreo 10 ori mai rapid.Este evident ca rapiditatea de calcul a produselor float * float in cazul lui 8051 nu se datoreaza lui insusi (arhitecturii interne si limbajului sau de asamblare) ci unui algoritm mai bun de generare a codului asembler din compilatorul lui Keil uVision4.
Link spre comentariu

Verifica asta:

You are not linking in the math library from AVR-LibC. GCC has a library that is used for floating point operations, but it is not optimized for the AVR, and so it generates big code
Link-uit math-ul si cu o simulare fara optimizari (oricum nu prea are ce optimiza) sunt necesari 1839 ciclii pentru o inmultire.
Prin "Link-uit math-ul" ce se intelege de fapt, doar adaugarea unei linii #include dupa #include in codul C sau mai trebuiesc si alte setari?
Link spre comentariu

Prin "Link-uit math-ul" ce se intelege de fapt, doar adaugarea unei linii #include dupa #include in codul C sau mai trebuiesc si alte setari?

-lm la linker.

 

Inmultirea a doua numere tip float este de fapt inmultirea a doi intregi (pe 32 biti de ex.) si adunarea altor doi (pe 8 biti de regula) deoarece orice cantitate cu virgula se poate scrie ca:

Nu chiar. Vezi standardul (IEE754) respectat.
Link spre comentariu

-lm la linker.

Stiu ca sunt plictisitor dar unde dau acel -lm la linker. Eu folosesc AVR Studio 4.18 si doar apas Build urmat de Run, nu stiu sa lucrez in linie de comanda.Am gasit calea asta:AVR Studio 4.18 / Meniu Project / Configuration Options / Libraries / Available link objects (libc.a, libm.a, + alte biblioteci) / Link with these objects.Adaug vreuna din bibliotecile de la lista "Available link objects" in caseta "Link with these objects"?
Link spre comentariu

libm.a este libraria de matematica.

 

Edit: Am rulat codul cu optimizari de gradul 3 si au rezultat 159 ciclii per inmultire intre 2 float-uri.

a=1.2456; //93b=1.1328; //105c = a*b; //117c = a*b; //276

Edit2: Si rulat pe codul tau:

#include <avr/io.h>uint8_t i, s;volatile uint8_t a8, b8;volatile uint8_t p16;volatile uint16_t a16, b16;volatile uint32_t p32;volatile float af, bf;volatile float pf;int main(void){   a8=143;   b8=249;   a16=37453;   b16=58274;   af=374.367893;   bf=58274.8982;      for (i=1;i<5;i++)   {    p16 = a8 * b8; // CC -> 213    p32 = a16 * b16; // CC -> 223    pf = af * bf; // CC -> 251    s = 1; // CC -> 402   }return 1;}
Link spre comentariu
Recomand sa studiezi totusi ce face un compilator caci golurile sunt mari, probabil si din lipsa de documentare tehnica asupra microcontrolerelor atmega sau ce simulezi.

1) Raspunsul nu este folositor. Alte ramarci nu mai fac deoarece as jigni.

Foarte bine faci.

 

uint16_t = uint8_t * uint8_t

uint32_t = uint16_t * uint16_t

Cu privire strict la codul de mai sus scris in C.

Care este greseala lui simplex din codul de mai sus? (aviz amatorilor)

 

Recomand ca orice test pe care il faceti, sa se termine cu verificarea rezultatelor, pentru a fi siguri ca ceea ce faceti este si corect.

Numaratul ciclilor nu valideaza un calcul matematic!!!

Link spre comentariu

libm.a este libraria de matematica.

Am rulat codul cu optimizari de gradul 3 si au rezultat 159 ciclii per inmultire intre 2 float-uri.

Deci printr-o simpla setare viteza de calcul a crescut de peste 10 ori.
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări