Go Down

Topic: Ottimizzare il codice per la velocità (Read 1 time) previous topic - next topic

GS88

Apr 11, 2012, 08:41 am Last Edit: Apr 11, 2012, 09:22 am by GS88 Reason: 1
Buongiorno a tutti, scusate la domanda...

Ho necessità di rendere una funzione il più veloce possibile (almeno nelle mie capacità)... Attualmente il codice è scritto in questo modo:

Code: [Select]
void eFire(unsigned int eTime){
 
 if(eTime>1000) eTime = 1000;
 if(eTime<70) eTime = 70;
 
 int eTimeMicro = (unsigned int)((1/eTime)*1000000);
 
 // Start first slider
 digitalWrite(FIRST, HIGH);
 delayMicroseconds(PULSE);
 digitalWrite(FIRST, LOW);
 
 delayMicroseconds(eTimeMicro);
 
 // Start 2nd slider
 digitalWrite(SECOND, HIGH);
 delayMicroseconds(PULSE);
 digitalWrite(SECOND, LOW);
}


C'è un modo? Cosa e come posso intervenire? In particolare mi chiedo quanto sono lenti i due if ed il calcolo di eTimeMicro? In teoria le digitalWrite potrei sostituirle con le rispettive istruzioni per la manipolazione delle porte... ma probabilmente non sono loro ad influire più di tanto.

Grazie.

leo72

E' una bella domanda. Bisognerebbe prendere il codice macchina generato dal compilatore e mettersi lì col datasheet per capire ogni istruzione che trovi quanto tempo di calcolo porta via e fare 2 somme.

GS88


E' una bella domanda. Bisognerebbe prendere il codice macchina generato dal compilatore e mettersi lì col datasheet per capire ogni istruzione che trovi quanto tempo di calcolo porta via e fare 2 somme.


Azz... grazie Leo! Mica cosa da poco...

Supponendo che la parte che a me interessa (quella dei digitalWrite) sia il più veloce possibile nel momento in cui mi serve, portar fuori questa parte di codice mettendolo in una variabile che poi passo alla funzione eFire()? In pratica calcolare eTime fuori dalla funzione, quando la velocità mi interessa meno... dentro la eFire mi risparmi questi calcoli e gli passo solo il valore...

Code: [Select]
 if(eTime>1000) eTime = 1000;
 if(eTime<70) eTime = 70;
 
 int eTimeMicro = (unsigned int)((1/eTime)*1000000);


astrobeed


In teoria le digitalWrite potrei sostituirle con le rispettive istruzioni per la manipolazione delle porte... ma probabilmente non sono loro ad influire più di tanto.


Invece pesano moltissimo, poco meno di 2 uS l'una, ovvero di più di quello che ci mette la if per fare il confronto e assegnare il valore, se le sostituisci con le relativa scrittura diretta dei pin tramite registri ci vuole solo un ciclo macchina (62.5 nS).
C'è però da tenere in considerazione che dentro la funzione hai dei delay di svariati millisecondi, quindi non vale la pena perdere tempo a sostituire le digitalwrite che complessivamente incidono circa 10 us contro un delay minimo di 1 ms.

Altra cosa, questo calcolo è a dir poco assurdo, non funziona perché non puoi dividere 1 con un valore int e aspettarti un valore diverso da 0.

Code: [Select]

int eTimeMicro = (unsigned int)((1/eTime)*1000000);


Devi fare così:

Code: [Select]

unsigned int eTimeMicro = 1000000L/eTime;




GS88

#4
Apr 11, 2012, 09:47 am Last Edit: Apr 11, 2012, 10:08 am by GS88 Reason: 1
Grazie  :smiley-red:

se le digitalWrite hanno quei tempi (credevo di più)... ho ben poco da fare.




lesto

scusate, ma vi preoccupate della velocità delle funzioni quando c'è una  delayMicroseconds(eTimeMicro); di mezzo?
secondo me quì c'è qualcosa che logicamente non funziona.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

GS88

#6
Apr 11, 2012, 11:36 am Last Edit: Apr 11, 2012, 12:01 pm by GS88 Reason: 1

scusate, ma vi preoccupate della velocità delle funzioni quando c'è una  delayMicroseconds(eTimeMicro); di mezzo?
secondo me quì c'è qualcosa che logicamente non funziona.


in che senso logicamente non funziona?

Funziona tutto. Quello che volevo sapere è quanto quegli if, dentro questa funzione anzichè fuori, potessero influire sull'esecuzione della funzione stessa.

Ossia se, portandoli fuori e passando il parametro alla funzione anzichè far eseguire questi controlli al suo interno potesse dare qualche vantaggio.

Il codice che vedi esegue perfettamente quello che deve fare. E tutti i delay che ci sono devono per forza di cose esserci.

Al massimo, posso con delle prove limare le delayMicroseconds tra i due digitalWrite per vedere se riesco a togliere qualcosa.

lesto

il fatto che ci siano errori logici non vuol dire che una cosa non funzioni. Si può spingere una automobile, ma se prima togli il freno a mano è più facile non trovi?

in questo caso il rallentamento del freno a mano è provocato dalle delay che hai sparso nel codice, che puoi sostituire con delle millis() se il tempo di attesa è > del tempo di esecuzione di tutto il loop.

gli if difficilmente sono ottimizzabili senza usare il codice macchina, ma per le digitalwrite puoi usare sbi & cbi (se non erro) che sono delle macro straveloci. se le cerchi nel forum dovresti trovare il codice in varie discussioni.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

astrobeed


in questo caso il rallentamento del freno a mano è provocato dalle delay che hai sparso nel codice, che puoi sostituire con delle millis() se il tempo di attesa è > del tempo di esecuzione di tutto il loop.


Che poi è la stessa cosa che gli ho detto io visto che c'è almeno un delay lungo come minimo 1 ms (eTime = 1000) e come massimo 14.28 ms (eTime = 70), quindi assolutamente trascurabili i tempi di esecuzione delle if e delle digitalwrite.

flz47655

La strada del datasheet con le istruzioni assembly è la strada del dolore.
Io in genere simulo con AVR Studio e controllo direttamente quanto impiegano le funzioni, molto comodo.

Ciao

astrobeed


Io in genere simulo con AVR Studio e controllo direttamente quanto impiegano le funzioni, molto comodo.


Con AvrStudio puoi simulare molto poco visti gli enormi limiti del suo simulatore, al limite lo fai tramite un ICE via hardware debug oppure con un DSO, meglio con un analizzatore di stati logici, utilizzando un pin come out per un impulso.
C'è sempre il sistema semplice di utilizzare la micros per misurare quanti microsecondi passano tra due punti distinti del programma.

IngHooch



C'è sempre il sistema semplice di utilizzare la micros per misurare quanti microsecondi passano tra due punti distinti del programma.



Anche io opterei per questa opzione ed in base a quello che ottieni ti regoli per fare quello che ti serve
The brightest flame burns quickest

GS88

Cerco di spiegare cosa fa il programma perchè non comprendo che vantaggi avrei andando ad usare la millis().

Allora, a parte le if che servono per calcolarmi i microsecondi di ritardo visualizzando dei valori 'leggibili' (sicuramente da chi userà il tutto), i delay servono per 'caricare' delle bobine. I tempi son quelli, sotto le bobine non vengono caricate.

Qual'è il vantaggio che avrei usando millis()?

La delayMicroseconds(eTimeMicro) mi serve per definire il ritardo di attivazione di una bobina rispetto all'altra. Anche qui quale vantaggio avrei ad usare una millis()?

Grazie.

lesto

attivi il pin, con la millis registri il tempo di attivazione, fai altro nel codice, nel frattempo ogni tanto (ogni loop di solito, ma puoi fare anche una funzione apposta che chiami quando ne hai voglia) controlli se hai superato il tempo di attesa, a quel punto disattivi il pin, ed eventualmente avvisi l'utente.
Come vedi ottieni una sorta di parallelismo, non sei bloccato nell'attesa ma puoi fare altro.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

astrobeed


Qual'è il vantaggio che avrei usando millis()?


Nessuno ti ha detto di usare la millis(), ti è stato detto che il tempo minimo, 1 ms, del delay all'interno della tua funzione è talmente grande che è irrilevante il tempo necessario per eseguire le altre istruzioni della funzione.

Go Up