Pages: 1 [2]   Go Down
Author Topic: risparmiare ram  (Read 2006 times)
0 Members and 1 Guest are viewing this topic.
Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 138
Posts: 9870
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Da prove che ho fatto in passato, usare un #define o un const byte per un pin è del tutto equivalente. Il compilatore ottimizza e l'impegno di ram finale dello sketch è identico sia usando la prima che la seconda soluzione.

Vero però c'è una differenza sostanziale tra i due metodi, se usi un const viene creata una variabile di tipo costante sfruttando la flash,  se usi #define viene sostituito il valore in fase di compilazione direttamente nell'espressione.
Utilizzando const il codice è di questo tipo

const byte pin 13;
digitalWrite(pin, HIGH);

Utilizzando "#define pin 13" la digitalWrite, dopo la compilazione, diventa equivalente a:

digitalWrite(13, HIGH);

Anche se la differenza può sembrare minima, quasi inutile, in realtà cambia molto a livello di run time perché nel primo caso il codice deve indirizzare una variabile per recuperare il valore di pin, nel secondo caso il valore è subito disponibile nel codice assembly senza doverlo recuperare, questo si traduce in diversi cicli macchina risparmiati e di conseguenza un codice più veloce.
Da notare che per accedere ad un valore posto nella flash è necessario utilizzare l'istruzione LPM (load Program Memory) che aggiunge un ulteriore overhead di cicli macchina per il recupero del valore di una variabile.




Logged

Offline Offline
Sr. Member
****
Karma: 8
Posts: 293
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

questo codice...

Code:
#define BOO 3

const byte bii = 2;

byte res;
byte ciccio;
void setup() {
 
 ciccio = BOO;
 res = bii;
}

void loop() {
   
  ciccio++;
  res++;
 
}

viene tradotto così:
Code:
00000000 <setup>:
   0:   83 e0           ldi     r24, 0x03       ; 3    <-- ciccio = BOO (DEFINE)
   2:   80 93 00 00     sts     0x0000, r24
   6:   82 e0           ldi     r24, 0x02       ; 2     <-- res = bii (const)
   8:   80 93 00 00     sts     0x0000, r24
   c:   08 95           ret

Disassembly of section .text.loop:

00000000 <loop>:
   0:   80 91 00 00     lds     r24, 0x0000
   4:   8f 5f           subi    r24, 0xFF       ; 255
   6:   80 93 00 00     sts     0x0000, r24
   a:   80 91 00 00     lds     r24, 0x0000
   e:   8f 5f           subi    r24, 0xFF       ; 255
  10:   80 93 00 00     sts     0x0000, r24
  14:   08 95           ret

ho dovuto complicarlo un po' perchè questo  compilatore non è proprio tanto rinc0glionito... fa delle ottimizzazioni non esattamente scontate... infatti pensavo di aver capito tutto ed invece non ho capito proprio nulla...
allora lasciando stare la parte <loop> dove l'unica cosa curiosa è che per incrementare di 1 un byte lui toglie 255  smiley-eek (...sti c@zzi) si vede che le due assegnazioni che ho fatto in setup sono tradotte pari pari.... quindi nessun risparmio in questo caso... quindi il mio messaggio precedente è del tutto errato: tanto per cambiare.

Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23123
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

astrobeed, ciò è vero su un PC ma avr-gcc compila ottimizzando il codice ed i 2 listati sono trasformati nello stesso identico sorgente assembly. Il compilatore vede appunto che la variabile PIN è una const e la tratta nello stesso identico modo di una #define.

Avevo già fatto a suo tempo delle prove, le ho rifatte stamani con i 2 listati che ho pubblicato qualche post prima: "define.txt" contiene la versione assembly dello sketch che usa la #define, "const.txt" quella invece che usa la const byte.
Risultato di diff eseguito su di essi:
Code:
[leo@desktop-hp build8853307674189123112.tmp]$ diff define.txt const.txt -s
I file define.txt e const.txt sono identici

* const.txt (13.39 KB - downloaded 19 times.)
Logged


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 138
Posts: 9870
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


ho dovuto complicarlo un po' perchè questo  compilatore non è proprio tanto rinc0glionito... fa delle ottimizzazioni non esattamente scontate...

Non è semplice, anche con poche righe di codice, capire cosa combina il compilatore e come ottimizza, spesso e volentieri il solo modo per verificare rapidamente se c'è stato un guadagno, o una perdita, di velocità sul nostro codice è fare delle misure strumentali.
Più tardi faccio un paio di prove, mirate a rilevare la reale differenza in cicli macchina tra l'uso di const e define, con l'utilizzo dell'analizzatore di stati logici in modo da poter misurare con precisione l'effettiva differenza.
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 138
Posts: 9870
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

astrobeed, ciò è vero su un PC ma avr-gcc compila ottimizzando il codice ed i 2 listati sono trasformati nello stesso identico sorgente assembly. Il compilatore vede appunto che la variabile PIN è una const e la tratta nello stesso identico modo di una #define.

No, non è così, a parte che pure sul pc valgono le stesse regole e i compilatori ottimizzano sempre e comunque, certo sul pc non hai la flash con tutte le relative problematiche, però rimane il fatto che una const è una variabile e la define è una sostituzione operata dal compilatore con relative differenze nei metodi di indirizzamento.
Comunque lasciamo la parola definitiva agli strumenti, che non mentono mai, e vediamo cosa viene fuori dal test pratico, dovrei riuscire a farlo in giornata.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23123
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non è semplice, anche con poche righe di codice, capire cosa combina il compilatore e come ottimizza, spesso e volentieri il solo modo per verificare rapidamente se c'è stato un guadagno, o una perdita, di velocità sul nostro codice è fare delle misure strumentali.
Più tardi faccio un paio di prove, mirate a rilevare la reale differenza in cicli macchina tra l'uso di const e define, con l'utilizzo dell'analizzatore di stati logici in modo da poter misurare con precisione l'effettiva differenza.

Ti ho appena mostrato che i 2 sketch il compilatore li trasforma nello stesso identico codice macchina.
Sul microcontrollore ci sarà quindi lo stesso binario, giusto? Quindi il comportamento è lo stesso.

Risultato di diff eseguito su di essi:
Code:
[leo@desktop-hp build8853307674189123112.tmp]$ diff define.txt const.txt -s
I file define.txt e const.txt sono identici
Logged


Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 5
Posts: 956
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

usando define però non posso usare PROGMEM, no?
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23123
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

usando define però non posso usare PROGMEM, no?
#define x y istruisce il compilatore a sostituire nel testo tutte le corrispondenze di "x" con "y", PROGMEM serve invece a dire al compilatore che i dati sono da prelevare dalla Flash.
Con #define non cambi solo dei valori ma puoi anche sostituire ad una parola chiave un qualcosa d'altro. Ad esempio PROGMEM è un alias creato con #define:
Code:
#define PROGMEM   __ATTR_PROGMEM__
che può essere poi riutilizzato:
Code:
#define PSTR ( s )   ((const PROGMEM char *)(s))
Logged


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 138
Posts: 9870
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Con #define non cambi solo dei valori ma puoi anche sostituire ad una parola chiave un qualcosa d'altro.

Con la define puoi anche creare delle macro, ovvero del codice vero e proprio collegato ad una parola chiave, p.e. cbi() e sbi() (clear bit e set bit) che vengono implementate tramite define:

Code:
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
Logged

Offline Offline
Sr. Member
****
Karma: 8
Posts: 293
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


ho dovuto complicarlo un po' perchè questo  compilatore non è proprio tanto rinc0glionito... fa delle ottimizzazioni non esattamente scontate...

Non è semplice, anche con poche righe di codice, capire cosa combina il compilatore e come ottimizza, spesso e volentieri il solo modo per verificare rapidamente se c'è stato un guadagno, o una perdita, di velocità sul nostro codice è fare delle misure strumentali.
Più tardi faccio un paio di prove, mirate a rilevare la reale differenza in cicli macchina tra l'uso di const e define, con l'utilizzo dell'analizzatore di stati logici in modo da poter misurare con precisione l'effettiva differenza.


si be ma l'assembler non mente... le due assegnazioni vengono tradotte proprio uguale come ha confermato il mio codice e anche leo. Ora si potrebbe discquisire se questi adeguamenti avvengono sempre in modo uguale oppure delle volte le costanti vengono effettivamente memorizzate in ram come sarebbe logico supporre (ma che non avviene).
...comunque veramente incredibile cosa fa il compilatore... se fai di seguito  ciccio = b; ciccio = c;... toglie proprio ciccio = b;
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 138
Posts: 9870
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ora si potrebbe discquisire se questi adeguamenti avvengono sempre in modo uguale oppure delle volte le costanti vengono effettivamente memorizzate in ram come sarebbe logico supporre (ma che non avviene).

Dipende molto anche dal livello di ottimizzazione impostato e se viene scelto di ottimizzare la velocità piuttosto che l'occupazione di memoria, sono due cose che spesso e volentieri sono in contrasto tra loro.
Detto in altri termini, non è detto che il compilatore faccia la stessa cosa, a parità di codice, con condizioni di ottimizzazione diverse.
Intanto ho fatto un primissimo test al volo e mi risulta che utilizzando la const, al posto della define, servono 187.5 ns in più, ovvero tre cicli macchina.
Più tardi, con calma, faccio un test più approfondito e posto i risultati completi delle misure strumentali.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 335
Posts: 23123
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Intanto ho fatto un primissimo test al volo e mi risulta che utilizzando la const, al posto della define, servono 187.5 ns in più, ovvero tre cicli macchina.
Più tardi, con calma, faccio un test più approfondito e posto i risultati completi delle misure strumentali.
Scusami, astro. Hai verificato se i 2 file binari sono diversi?
Logged


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 138
Posts: 9870
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Scusami, astro. Hai verificato se i 2 file binari sono diversi?

Il file è uno solo perché ho inserito nello stesso sketch tutti e due i test in modo da rilevare i tempi delle due condizioni con una singola misura in cascata.
Però prima di esprimermi in modo definitivo voglio approfondire meglio le cose.
Logged

Offline Offline
Sr. Member
****
Karma: 8
Posts: 293
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

magari se postassi anche l'assembly sarei curioso.
...se non ti risulta pesante...ho l'impressione di sembrare un po' un'invasato con questo asm. smiley-red
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 138
Posts: 9870
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

magari se postassi anche l'assembly sarei curioso.

Posterò lo sketch usato e gli screen capture delle misure strumentali, se vuoi vedere l'assembly basta che compili e dai il file .elf in pasto a AvrStudio smiley
Logged

Pages: 1 [2]   Go Up
Jump to: