Go Down

Topic: Scheduler ufficiale (Read 15234 times) previous topic - next topic

vbextreme

si ma così facendo potrebbe essere fin troppo facile far avverare la condizione di una funzione che nn verrà mai eseguita.
Mettiamo f1 tempo 240 e f2 tempo 250
f1 tick 240 ora richiama la funzione che dura 20 tick e mettiamo che f2 era sempre a 240 ora con questi 20 tick hai sforato e sei passato a 5 e la funzione non viene eseguita.
Non pensare che sia un caso limite ma con più task attivi "skippare" una funzione anche ciclicamente diventa fin troppo facile, pericoloso e insicuro! per rimediare tocca mettere mano pesantemente al codice e a quel punto non conviene fare tutto manualmente?
Easy framework linguaggio C: https://github.com/vbextreme/EasyFramework
Hack your life: http://vbextreme.netai.net/
Unoffical Telegram group: https://telegram.me/joinchat/ALRu8ACkdTdXyz-2P7v13A

astrobeed

ra con questi 20 tick hai sforato e sei passato a 5 e la funzione non viene eseguita.
A parte che viene eseguita comunque visto che il tempo è scandito sotto interrupt, quindi non appena la gestione torna allo scheduler vengono mandate in esecuzione le funzioni in attesa, ovviamente in ritardo, in tutti i casi quando si lavora con scheduler minimali come questo uno dei prerequisiti è che la singola funzione non deve durare di più dell'intervallo con quella seguente.
Del resto 16 ms, tick minimo, sono un'eternità dal punto di vista di una MCU e se il codice è scritto come si deve una funzione, qualunque funzione, non può durare così tanto, se ci sono dei limiti imposti da timing esterni, p.e. attendere il ready di un sensore, la funzione deve essere scritta in modo da poter gestire il polling senza essere bloccante, però in questi casi è meglio lavorare event driven utilizzando gli interrupt.
Scientia potentia est

vbextreme

Quote
A parte che viene eseguita comunque visto che il tempo è scandito sotto interrupt
f1 time 240
f2 time 250

primo sequenze()
...
f1 contatore 239
f2 contatore 239
...
f1 240 lancio funzione
f1 run, isr->f2 contatore++
...
f1 run, isr->f2 240 + 20 tick persi = contatore = 5

eccoci, mi sono spiegato?
come hai fatto notare però un tempo elevato di tick risolve parzialmente il problema perché comunque rimane li in attesa di fregarti.
usando però tick elevati si hanno enormi latenze,  il chip rimarrebbe spesso inutilizzato, esempio
f1 tempo 1
f2 tempo 2
si ha una latenza di tempo(f1) - tempo(tick), se la tua funzione dura 5 ms per il restanti 11ms eseguì loop vuoti.Per non parlare del ritorno da 1 !
Più che uno scheduler sembra un timer!
sembra che richiami le varie funzioni ogni x secondi come farebbe un comunissimo timer, lo scheduler invece si impegna a utilizzare sempre tutta la CPU e cerca di garantire una sorta di parallelismo.
Easy framework linguaggio C: https://github.com/vbextreme/EasyFramework
Hack your life: http://vbextreme.netai.net/
Unoffical Telegram group: https://telegram.me/joinchat/ALRu8ACkdTdXyz-2P7v13A

astrobeed

f1 run, isr->f2 240 + 20 tick persi = contatore = 5
Questo può succedere solo se si lavora al limite del contatore e con funzioni scritte male che possono andare a sforare, però ti rammento che il tick dura 16 ms e 255 * 16 = 4080 ms, è raro lavorare con tempi così lunghi, se serve di più basta usare lo specifico contatore definendolo unsigned int.

Quote
come hai fatto notare però un tempo elevato di tick risolve parzialmente il problema perché comunque rimane li in attesa di fregarti.
Su Arduino il tempo di tick alto è dovuto alla temporizzazione minima del watchdog, per l'appunto 16 ms, è possibile scendere al singolo ms, o meno, usando un timer però in questo modo impatti su come Arduino usa i timer e rischi di togliere risorse importanti come canali pwm o altre funzioni di temporizzazione.
Rammento che qRTOS è scritto specifico per Arduino per cui oltre ai limiti delle mcu a 8 bit c'è da fare i conti con i limiti di Arduino, in compenso è impatto quasi zero sulle risorse e disturba il normale funzionamento di Arduino.

Quote
usando però tick elevati si hanno enormi latenze,  il chip rimarrebbe spesso inutilizzato, esempio
Mica vero, dipende da cosa devi fare, tutto quello che è presente nella loop viene eseguito costantemente pertanto non è detto che la mcu non faccia nulla.
In tutti i casi con le piccole mcu capita spesso che lavorano solo per una percentuale del tempo macchina, il resto non fanno nulla o vengono messe in sleep per ridurre i consumi, esempio pratico ogni 100 ms devi leggere lo stato di un port, se è cambiato dall'ultima lettura hai delle elaborazioni da fare, ogni 200 ms devi inviare sulla seriale delle informazioni, la mcu passa praticamente la maggior parte del tempo senza fare nulla, e non si tratta di una caso particolare, è quasi sempre la norma con le mcu.

Quote
sembra che richiami le varie funzioni ogni x secondi come farebbe un comunissimo timer, lo scheduler invece si impegna a utilizzare sempre tutta la CPU e cerca di garantire una sorta di parallelismo.
Non è vero che lo scheduler si impegna ad usare tutta la cpu, sopratutto se parliamo di RTOS dove non è il sistema operativo a decidere chi e per quanto tempo un codice deve girare, sono io programmatore che decido quali routine devono girare, quando devono farlo e per quanto tempo, lo scheduler si limita a gestire questi processi con le mie regole.
L'anarchia dei sistemi operativi non real time, p.e. Windows e Linux, non è cosa gradita sulle MCU dove la fanno da padroni gli RTOS, o comunque sistemi che consentono di gestire come serve i vari task.
Ti rammento che stiamo parlando di piccole mcu 8 bit, con risorse molto limitate, in particolare di Arduino con tutti i paletti che pone, non stiamo parlando di software per pc o un sistema embedded di fascia alta.


Scientia potentia est

BaBBuino

Testato mi ha detto che qua si litiga, con chi devo incominciare? :D

BaBBuino

Ho letto tutto e purtroppo devo dare ragione su tutto ad Astrobeep.

VBextreme di che cosa ti occupi nello specifico? Così facciamo prima a capire perchè hai detto quello che hai detto... :D

nid69ita

@Babbuino, e che invito a fare se non a presentarsi ?   :smiley-mr-green:
http://forum.arduino.cc/index.php?topic=113640.msg2229698#msg2229698
my name is IGOR, not AIGOR

BaBBuino

#37
Jun 24, 2015, 08:04 pm Last Edit: Jun 24, 2015, 08:14 pm by BaBBuino
f1 time 240
f2 time 250

primo sequenze()
...
f1 contatore 239
f2 contatore 239
...
f1 240 lancio funzione
f1 run, isr->f2 contatore++
...
f1 run, isr->f2 240 + 20 tick persi = contatore = 5

eccoci, mi sono spiegato?
come hai fatto notare però un tempo elevato di tick risolve parzialmente il problema perché comunque rimane li in attesa di fregarti.
usando però tick elevati si hanno enormi latenze,  il chip rimarrebbe spesso inutilizzato, esempio
f1 tempo 1
f2 tempo 2
si ha una latenza di tempo(f1) - tempo(tick), se la tua funzione dura 5 ms per il restanti 11ms eseguì loop vuoti.Per non parlare del ritorno da 1 !
Più che uno scheduler sembra un timer!
sembra che richiami le varie funzioni ogni x secondi come farebbe un comunissimo timer, lo scheduler invece si impegna a utilizzare sempre tutta la CPU e cerca di garantire una sorta di parallelismo.
Gli AVR, ovviamente, sono estremamente limitati, ma con una MCU un pò più evoluta (un dsPIC o un PIC32) la granularità del clock (leggi velocità) è tale che è possibile impiegare anche un doppio scheduler usando due timer separati.

Uno scheduler legato ad timer (e relativo Interrupt) per le funzioni ad alta priorità, ed uno scheduler legato ad un secondo timer per le funzioni, diciamo di servizio, per il quali la latenza (cmq sempre limitata) non è un problema. Inoltre si possono utilizzare due risoluzioni diverse per i Tick, con buon pace delle latenze: poco importanti per i servizi, importantissime per i Task principali.

Inoltre i PIC32 (per esempio) gestiscono nativamente le code per le priorità degli interrupt, ed hanno una gestione degli stessi talmente flessibile e ben congegnata che, a meno di non aver scritto le routine con i piedi, i problemi che poni sono facilmente ovviabili.

E ancora: dispongono di un "Shadow register set" ovvero di un set di registri ulteriori, per cui il Context Switch è ulteriormente ridotto, anzi, swappando questi registri con i principali, non serve nemmeno più fare un Context Switch.
Quindi, l'ipotesi dello sforamento temporale, sebbene possibile, non è così facile che accada.

Certo che poi va ingegnerizzato per bene il software, è necessario fare i conti della serva fino al conteggio dei cicli di clock delle singole istruzioni e/o funzioni e cautelarsi stando abbondanti con il Tick, ma è ordinaria amministrazione per chi sviluppa questo genere di firmware. Siamo anni luce dalla programmazione "spannometrica" di Arduino, fatta per lo più con i piedi.

BaBBuino

Dimenticavo, non necessariamente uno Scheduler deve garantire il massimo sfruttamento della CPU. Ci possono benissimo essere dei tempi morti, generalmente occupati dal ciclo principale (loop() o While(1)) oppure da una funzione apposita che negli RTOS è genericamente chiamata con qualcosa di simile a Task_Idle(), la quale può servire per misurare quanto tempo "disponibile" rimane per ulteriori successivi Task, far girare servizi in background, oppure semplicemente mettere a nanna il processore (sleep()).

vbextreme

#39
Jun 25, 2015, 12:12 am Last Edit: Jun 25, 2015, 12:16 am by vbextreme
@bubbuino nello specifico non so neppure io di cosa mi occupo, diciamo che parto con il gestire un gruppo di meccanici specializzati in macchinari oleodinamici industriali.Ma non so più se codesto sia più il lavoro principale, per rimanere nell'ambito software capita di essere ingaggiato per risolvere qualche pasticcio del guru di turno, tale per me è nata come passione ben più di due decadi fà.

A parte il solito discorso dei chippini e chipponi e altre smancierie poco interessanti, mi soffermerei sul thread che dopotutto è già abbastanza complesso per essere affrontato su un forum.

@Astro ho esattamente detto che il problema c'è e rimane, per "tamponare" il difetto o più conosciuto come bug bisogna mettere mano al codice e spesso alla logica del programma, ops, firmware, sketch...non ho detto che non sia risolvibile ma semplicemente che con tale algoritmo di scheduling tale bug rimarrà sempre presente, pronto e in agguato a fregarti la prima volta che sei distratto.
A parte tutto il resto che naturalmente hai detto sacrosante parole qui ti cito:
Quote from: @Astro
sono io programmatore che decido quali routine devono girare, quando devono farlo e per quanto tempo,
Belle parole, proprio quelle che ho cercato di usare io all'inizio di questo thread, peccato che nel tuo scheduler tutto ciò non avviene.
Non hai nessuna sorta di garanzia che f() venga eseguita quando vuoi te, quello scheduler non lo permette! Non permette nemmeno di terminare un task!
Non fa altro che richiamare funzioni in un certo lasso di tempo senza nemmeno preoccuparsi più di tanto, delega al programmatore tutto! e allora faccio da me! a che serve tale ciclo se poi devo fare tutto a mano? mi sembra solo un'inutile complicazione.
Certo che se fosse stato messo in una lista circolare con gestione tempi e priorita allora si che si poteva chiamare scheduler! e non mi riferisco certo ai mainstream, è fattibilissimo anche su sti chippettini senza sprecare neanche troppa memoria, forse un pelo di calo prestazionale ma dopotutto invece di farle fare niente posso gestire correttamente una coda con priorità.
Easy framework linguaggio C: https://github.com/vbextreme/EasyFramework
Hack your life: http://vbextreme.netai.net/
Unoffical Telegram group: https://telegram.me/joinchat/ALRu8ACkdTdXyz-2P7v13A

dally

no doubt useful to multitask light bulbs on the christmas tree :D

vbextreme

 :D  :D   :D  :smiley-mr-green:  :smiley-mr-green:  :smiley-eek-blue:  :smiley-eek:  :smiley-money:  :smiley-twist:
Easy framework linguaggio C: https://github.com/vbextreme/EasyFramework
Hack your life: http://vbextreme.netai.net/
Unoffical Telegram group: https://telegram.me/joinchat/ALRu8ACkdTdXyz-2P7v13A

testato

Questo significa essere bastardi  :)

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

astrobeed

ma semplicemente che con tale algoritmo di scheduling tale bug rimarrà sempre presente, pronto e in agguato a fregarti la prima volta che sei distratto.
Come direbbe Steve, "it's not a bug, it's a feature" :D
In tutti i casi continui a scordarti che stiamo parlando di Arduino, modelli basati su AVR, il che limita molto le possibilità, il semplice schedelur che ho illustrato è pensato per girare senza disturbare il normale funzionamento di Arduino e senza sottrarre nessuna risorsa.
Su altri micro, con altre risorse disponibili, senza wiring tra i piedi, uso soluzioni decisamente migliori e più performanti, sempre se non esiste uno scheduler già fatto che funziona bene, non sto a scoprire l'acqua calda :)
Altro dettaglio, su micro/mcu quello che serve realmente è un RTOS, di un normale OS non ci si fa nulla, ne esistono anche per otto bit, però impattano molto sulle risorse, spesso fanno molto di più di quanto necessario e non sono scalabili, vale per quelli free perché quelli a pagamento (= $$$) sono fortemente scalabili e ottimizzabili.
Un RTOS free molto gettonato è il FreeRTOS, ne hanno fatto il porting per quasi tutti i micro/mcu, il che include anche gli AVR, ovviamente su piccoli micro/mcu ha svariate limitazione ed omissioni.
Di FreeRTOS esiste un porting per Arduino sotto forma di libreria, mai provato e non ho idea di quello che riesce a fare e quanto impatta su wiring, questa potrebbe una missione per Testato :D
Scientia potentia est

astrobeed

Dimenticavo, la "nuova" frontiera della programmazione embedded è usare un main cycle composto esclusivamente da "while(1);", non sto scherzando in Arduino diventa una cosa simile:

Code: [Select]


void Setup()
{
  // init periferiche e variabili
}


void Loop()
{

 // eventuali operazioni preliminari

 while(1);

}




In pratica tutto il codice è gestito tramite un sistema di scheduling, come quello che ho illustrato, e le periferiche sono tutte interrupt driven, in pratica ogni tot ms lo scheduler verifica le operazioni pendenti legate alle periferiche, dipende dai relativi flag settati durante le ISR, e le risolve, inoltre gestisce tutti gli altri task per le operazioni non interrupt driven.

Scientia potentia est

Go Up