PDA

View Full Version : [C/C++] problemi di determinismo


misterx
24-07-2011, 08:48
sto lavorando in ambiente windows xp e sapendo che tale sistema operativo possiede uno schedule ti tipo NON deterministico mi chiedevo come bypassare tale limitazione per avere almeno in parte dei tempi corretti.

Qualcuno che ha avuto esperienze di programmazione di questo tipo (real time) su sistemi non deterministici potrebbe illuminarmi?

grazie

gugoXX
25-07-2011, 11:54
Ciao.
Una cosa che ricordo e' che il problema non e' legato a Windows o altro sistema operativo.
Non e' possibile creare un vero "real time" sulle nostre macchine a causa della natura del meccanismo degli interrupt del microprocessore.

Poi ci si potra' accontentare, ma resta un real Time like, non vero.

sottovento
25-07-2011, 12:15
sto lavorando in ambiente windows xp e sapendo che tale sistema operativo possiede uno schedule ti tipo NON deterministico mi chiedevo come bypassare tale limitazione per avere almeno in parte dei tempi corretti.

Qualcuno che ha avuto esperienze di programmazione di questo tipo (real time) su sistemi non deterministici potrebbe illuminarmi?

grazie

Di quali tempi parli, in particolare? Suppongo ti riferisca ai tempi di esecuzione (in questo caso, determinismo = stessa durata delle esecuzioni di risposta ad eventi esterni).

Non l'ho mai provato, ma per quel poco che ne so c'e' la possibilita' di alzare la priorita' di un processo al livello real time. Non ho idea di QUANTO real time sia, ma penso che si possa trovare in rete qualche informazione.

sottovento
25-07-2011, 12:18
Ciao.
Una cosa che ricordo e' che il problema non e' legato a Windows o altro sistema operativo.
Non e' possibile creare un vero "real time" sulle nostre macchine a causa della natura del meccanismo degli interrupt del microprocessore.

Poi ci si potra' accontentare, ma resta un real Time like, non vero.

No, dai! E' un po' drastico.
Prima di tutto, occorrerebbe sapere quale livello di determinismo ci si pone come obiettivo.
Ma... sono sempre esistiti i sistemi operativi real time! I piu' famosi, per esempio, sono QNX o VxWorks, i quali ottengono un buon livello di prestazioni mediante schedulazione "run to completion" basata su priorita', con preemption.

Ovviamente il time sharing e' proibito :D

misterx
25-07-2011, 12:37
Di quali tempi parli, in particolare? Suppongo ti riferisca ai tempi di esecuzione (in questo caso, determinismo = stessa durata delle esecuzioni di risposta ad eventi esterni).

Non l'ho mai provato, ma per quel poco che ne so c'e' la possibilita' di alzare la priorita' di un processo al livello real time. Non ho idea di QUANTO real time sia, ma penso che si possa trovare in rete qualche informazione.

ciao,
le informazioni che ho a riguardo e che mi sono state riferite sono che windows dedica ogni tot dempo non determinabile, di 10 ms per riorganizzare memoria e/o altro, chiamiamoli usi interni.
Per l'appilcativo che sto scrivendo io, siccome acquisisce segnali via ethernet, indagando mi hanno riferito gli stessi costruttori delle schede di cui acquisisco lo stato dei segnali che il ritardo esistente sulla ethernet da loro misurato è di 33 ms.

Il mio problema è dare un valore di riferimento, un dato di targa al mio programma nel senso che io possa dire che tale software è in grado di campionare segnali in un intorno di x ms.

Detto quanto sopra, ho scritto il programma usando thread e non rilevo affatto i ritardi che mi sonon stati riferiti, ma al massimo quelli che impongo io ai vari thread per non sollecitare troppo la CPU e lasciare spazio agli altri programmi.

Ho campionato 1 milione di segnali con un ritardo massimo, misurato tra il thread che legge il segnale su ethernet e tra il thread che scrive, di 16 ms.
Il thread che legge viene eseguito ogni 20 ms, quello che scrive ogni 50 ma il tempo che intercorre tra il momento in cui windows dedica tempo al thread che legge e il thread che scrive è quello che ho specificato cioè, 16 ms.

In uno scenario del genere, che tempistiche dichiaro per il mio programma?

jappilas
25-07-2011, 13:46
Ciao.
Una cosa che ricordo e' che il problema non e' legato a Windows o altro sistema operativo.oddio, in realtà sì
se si considerano sistemi general purpose (come windows, linux ecc) e si pensa alle finalità con cui sono nati (in funzione di quale tipo di workload e di quale modello progettuale per quanto riguarda le applicazioni) si nota che la priorità era sostanzialmente massimizzare il throughput del sistema in presenza di task batch
ma massimizzare il throughput è per certi versi antitetico all' esigenza primaria in ambito realtime che è dato un evento, gestirlo (quindi saltare alla porzione di codice appropriata -e/o attivare il processo relativo- ed eseguirla) nel minor tempo possibile (nel caso del realtime hard, in un tempo deterministico o quantomeno superiormente limitato con il limite superiore certo e documentato), motivo per cui in ambito realtime sono diverse sia le politiche di scheduling sia le modalità con cui operano i progettisti di applicazioni

questi ultimi spesso analizzeranno come prima cosa le richieste computazionali della/e loro applicazione/i per determinarne i vincoli temporali minimi (WCET - worst case execution times) e sceglieranno un sistema operativo realtime capace di garantire su quel certo hw latenze compatibili con quei vincoli di modo da assicurare la schedulabilità del sistema
il sistema operativo RT dal canto suo sarà implementato in maniera tale per cui latenze di scheduling e di esecuzione delle system call saranno se non costanti (indipendenti dal numero di oggetti/processi/file/... ) quantomeno superiormente limitate, basato su un kernel preemptible (*) (che con buona probabilità sarà un microkernel **) e magari metterà a disposizione (in effetti imporrà) dei protocolli di resource reservation (***) - allora starà al progettista strutturare e calibrare il sistema
e già a questo punto sarà chiaro che lo sviluppo di una sistema RT è un processo a priori e olistico ...

*: rendere il kernel stesso tutto o quasi interrompibile (naturalmente tranne quelle parti che eseguono operazioni atomiche, ma queste possono essere contenute in sezioni di relativamente poche righe di codice invece di imporre la non interrompibilità dell' intero kernel o sottosistema) quindi reattivo a eventi come appunto interrupt e capace di notificare tali eventi a task userspace (oltre che di schedularli) è il passo più determinante verso la riduzione delle latenze,
**: questo perchè il uK si presta meglio alla minimizzazione dei code path e al loro auditing - cosa per cui occorre che la code base sia il più compatta e gestibile possibile - non per presunte maggiori prestazioni che anzi su un microkernel sono tipicamente sacrificate dal fatto stesso di avere agenti server in processi separati (ma come si diceva prima, nel realtime contano affidabilità e latenze, più che throughput)
***: un' applicazione potrà essere accettata per l' esecuzione solo se le sue richieste in termini di risorse - tempo cpu e memoria - sommate al carico attuale non superano una soglia (iirc dipendente dall' algoritmo di scheduling, in certi casi intorno al 75-80%, al di sopra del quale la gestione non è più garantita)
Non e' possibile creare un vero "real time" sulle nostre macchine a causa della natura del meccanismo degli interrupt del microprocessore.

Poi ci si potra' accontentare, ma resta un real Time like, non vero.questa, scusami, ma mi giunge nuova
sistemi come QNX e VXWorks esistono e girano sull' hw in circolazione, prevalentemente su piattaforma ARM (perchè più diffusa in ambito embedded) ma mi risulta anche X86 - e qnx e vxworks sono sistemi real time HARD (capaci -di loro- di assicurare il rispetto dei vincoli temporali in ambiti - avionica, automotive, controlo di centrali nucleari ecc - in cui superamento di una deadline implica fallimento del sistema)
per cui tenderei a escludere sia un problema di interrupt, più un problema di concezione (ma anche finalità) dell' OS (e più precisamente del kernel)

riprendendo il discorso di cui sopra, un kernel non concepito in funzione del realtime, quindi
- con tempi di reazione a interrupt non noti costanti o non superiormente limitati (se non proprio capace di perdersi degli interrupt a causa della possibilità di stare eseguendo del codice non interrompibile, quindi con interrupt disabilitati, nel momento in cui si verifica un evento)
- con tempi di esecuzione delle syscalls non noti costanti o non superiormente limitati dovuti a implementazione non O(k) delle syscall stesse - cosa che in apparenza non è un problema o lo è solo se gli interrupt restano disabilitati per tempi lunghi... in realtà si trascura che anche i processi RT come qualunque altro processo eseguono IO, ma trattandosi di processi RT la possibilità di completare tutte le proprie operazioni prima della deadline è cruciale per il successo o fallimento del sistema, quindi è fondamentale che anche le sytem call siano caratterizzate da tempi superiormente limitati

può al più "cercare" di eseguire processi real time riducendo quanto possibile le latenze (ma su un kernel monolitico o ibrido è assai più complicato se non impossibile a causa delle dimensioni -di vari ordini di grandezza maggiori -della code base del kernel stesso) e aumentando la priorità (su windows e linux i processi RT vengono eseguiti prima dello stesso scheduler e di ogni altro processo, che in effetti rischia di andare in starving ) ma di più non può fare e non può comunque offire garanzie, trattandosi di un compromesso tecnologico realizzato con differenti priorità

jappilas
25-07-2011, 13:47
No, dai! E' un po' drastico.
Prima di tutto, occorrerebbe sapere quale livello di determinismo ci si pone come obiettivo.
Ma... sono sempre esistiti i sistemi operativi real time! I piu' famosi, per esempio, sono QNX o VxWorks, i quali ottengono un buon livello di prestazioni mediante schedulazione "run to completion" basata su priorita', con preemption.ti chiedo scusa, quando stavo scrivendo (ci ho messo un po') il tuo post non c' era ancora :O

Ovviamente il time sharing e' proibito :Ded anche il paging con swap su disco :D

banryu79
25-07-2011, 15:12
Ho campionato 1 milione di segnali con un ritardo massimo, misurato tra il thread che legge il segnale su ethernet e tra il thread che scrive, di 16 ms.
Il thread che legge viene eseguito ogni 20 ms, quello che scrive ogni 50 ma il tempo che intercorre tra il momento in cui windows dedica tempo al thread che legge e il thread che scrive è quello che ho specificato cioè, 16 ms.

Ciao, scusa se probabilmente sottolineo una cosa che hai già controllato, ma come hai "misurato" (chiamando quali API di Windows) questa latenza?
Perchè se non sbaglio per poter effettuare misurazioni precise di quantità molto piccole di tempo bisogna utilizzare gli "High Performance Counter" (timer ad alta precisione, altrimenti in Windows c'è una granularità di cira 15,qualcosa millisec, e il valore della tua misura mi suona appunto "sospetto").
Qui c'è una pagina (http://www.decompile.com/cpp/faq/windows_timer_api.htm), purtroppo di più non so dirti.

gugoXX
25-07-2011, 17:26
No, dai! E' un po' drastico.
Prima di tutto, occorrerebbe sapere quale livello di determinismo ci si pone come obiettivo.
Ma... sono sempre esistiti i sistemi operativi real time! I piu' famosi, per esempio, sono QNX o VxWorks, i quali ottengono un buon livello di prestazioni mediante schedulazione "run to completion" basata su priorita', con preemption.

Ovviamente il time sharing e' proibito :D

Sulle "nostre macchine" intendevo sui nostri microprocessori, non su "Tutti" i microprocessori.
Nostri ovvero gli x86, ma anche la famiglia 680x0.
E il problema era proprio dovuto a come sono gestiti interrupt.

marco.r
25-07-2011, 17:47
Sulle "nostre macchine" intendevo sui nostri microprocessori, non su "Tutti" i microprocessori.
Nostri ovvero gli x86, ma anche la famiglia 680x0.
E il problema era proprio dovuto a come sono gestiti interrupt.

Non mi risulta. Ad esempio le varianti real-time di linux (e.g. Xenomai) fanno in modo che il processo real-time abbia priorita' rispetto agli interrupt handlers non real-time (kernel compreso).
L'unico grosso problema per le macchine x86 attualmente sono gli SMI visto la cpu e il sistema neanche se ne accorgono, e quindi bisogna usare dei workaround per disabilitarli (con risultati variabili a seconda della scheda madre).

marco.r
25-07-2011, 17:56
ti chiedo scusa, quando stavo scrivendo (ci ho messo un po') il tuo post non c' era ancora :O

ed anche il paging con swap su disco :D
E anche le allocazioni di memoria :D
Cmq se siamo nell'ordine di una ventina di millisecondi, dovrebbe essere in grado ottenere prestazioni accettabili a patto di
- Impostare la priorita' massima per il processo interessato
- Spostare l'output su disco (o su rete) su un altro thread/processo
- Evitare allocazioni di memoria durante il loop
- Tenere basso il carico della macchina.

Il problema piu' grosso e' probabilmente la lettura da rete, li' l'unica cosa pratica che mi viene in mente e' evitare al massimo altro traffico che non sia quello dell'applicazione, magari isolando il computer dalla LAN "generale".

Potrebbe valer la pena di valutare una versione hard real time di windows (CE o XP Embedded) anche se non ho alcuna esperienza con queste... e comunque come dicevo le latenze in gioco non sono poi eccessivamente basse.

pabloski
25-07-2011, 18:06
sto lavorando in ambiente windows xp e sapendo che tale sistema operativo possiede uno schedule ti tipo NON deterministico mi chiedevo come bypassare tale limitazione per avere almeno in parte dei tempi corretti.

Qualcuno che ha avuto esperienze di programmazione di questo tipo (real time) su sistemi non deterministici potrebbe illuminarmi?

grazie

è necessario xp? in questo caso non c'è nulla che tu possa fare

se invece puoi optare per altro potresti considerare qnx o baremetal

misterx
25-07-2011, 18:13
Ciao, scusa se probabilmente sottolineo una cosa che hai già controllato, ma come hai "misurato" (chiamando quali API di Windows) questa latenza?
Perchè se non sbaglio per poter effettuare misurazioni precise di quantità molto piccole di tempo bisogna utilizzare gli "High Performance Counter" (timer ad alta precisione, altrimenti in Windows c'è una granularità di cira 15,qualcosa millisec, e il valore della tua misura mi suona appunto "sospetto").
Qui c'è una pagina (http://www.decompile.com/cpp/faq/windows_timer_api.htm), purtroppo di più non so dirti.

questa non la sapevo, io mi sono affidato alla GetLocalTime() che senza approfondire ritenevo precisa

Ho trovato anche questo esempio http://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter

misterx
25-07-2011, 18:15
è necessario xp? in questo caso non c'è nulla che tu possa fare

se invece puoi optare per altro potresti considerare qnx o baremetal

ciao,
devo usare XP un quanto su tale sistema operativo girano già altri programmi e non è possibile cambiarlo pena la riscrittura completa degli altri programmi e sono troppi

tacchinox
25-07-2011, 18:35
forse con xp embedded qualcosa ci cavi, altrimenti potresti usare win CE che è piu' indicato.
Con l'XP normale il real time è irreale.

Ma poi perche' non usi delle schede dedicate per l'acquisizione, con il loro sistema operativo ovviamente, e con l'XP ci analizzi solo i buffer?
Io lavoro nell'automazione e di soluzioni ce ne sono a tonnellate, basta pagare...
Per farti un esempio la National instruments ha sicuramente qualcosa su bus PXI o quello che è.

misterx
25-07-2011, 19:08
forse con xp embedded qualcosa ci cavi, altrimenti potresti usare win CE che è piu' indicato.
Con l'XP normale il real time è irreale.

Ma poi perche' non usi delle schede dedicate per l'acquisizione, con il loro sistema operativo ovviamente, e con l'XP ci analizzi solo i buffer?
Io lavoro nell'automazione e di soluzioni ce ne sono a tonnellate, basta pagare...
Per farti un esempio la National instruments ha sicuramente qualcosa su bus PXI o quello che è.

perchè XP è già usato per altri scopi e non posso sostituirlo, per il momento.
Terminato questo progetto mi orienterò su windows xp embedded o windows CE o Linux.

Già avere il tempo speso in modo preciso come mi ha suggerito banryu79 ho idea che mi porterà sulla strada giusta

banryu79
25-07-2011, 19:13
Ho trovato anche questo esempio http://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter
[OT]
Commentato nientepopodimenoche da Alex Martelli, alla faccia! :D

misterx
25-07-2011, 19:27
[OT]
Commentato nientepopodimenoche da Alex Martelli, alla faccia! :D

quindi vado sul sicuro :)

Non ho capito se il numero di tick si basa sulla percentuale d'uso della CPU o altro ed anche se oltre questo metodo che ho già implementato grazie a te e ad Alex sia il più preciso possibile


p.s.
si direbbero variazioni di stato ALTO/BASSO del chip di clock

banryu79
25-07-2011, 19:54
Ripeto: non so molto, a parte quello che ho letto, perchè son questioni con cui non ho mai avuto a che fare direttamente (in Java uso System.nanoTime() e tutto quello che so è che la jvm in Windows è implementata appoggiandosi alle QueryPerformanceCounter/QueryPerfomanceFrequency API, se disponibili).
Cosa vadano a toccare le QPC API, a livello di hardware, non saprei.

misterx
25-07-2011, 20:02
ok grazie, approfondisco io

ciao

misterx
25-07-2011, 20:28
questo è quello che mi racconta quella funzione

11, 2.4, (63) [[[18,2908721639203]]]
8, 2.0, (156) [[[1,65467957519741]]]
12, 3.8, (32) [[[17,2390625065476]]]
8, 2.4, (32) [[[1,64825417755609]]]
12, 3.0, (31) [[[17,2602942552755]]]
10, 1.2, (62) [[[1,69714307265309]]]
12, 3.8, (31) [[[17,6198371580746]]]
11, 2.4, (31) [[[1,72144783764417]]]
8, 2.4, (63) [[[17,4351768171653]]]
11, 2.4, (31) [[[2,27933997197968]]]
11, 2.4, (63) [[[17,9307705308915]]]
12, 3.8, (32) [[[2,3891304621118]]]
12, 3.0, (93) [[[17,3318117246745]]]
12, 3.0, (31) [[[1,74491450729073]]]
11, 2.0, (31) [[[17,2762180668213]]]
12, 3.0, (187) [[[1,63707957296249]]]
11, 2.0, (31) [[[17,3033164829608]]]
8, 2.0, (63) [[[1,72647640971129]]]
12, 3.0, (32) [[[16,8985164315576]]]
5, 5.32, (63) [[[1,66194306818325]]]
12, 3.0, (31) [[[17,3287387084113]]]
12, 3.0, (93) [[[1,69686370753825]]]
12, 3.0, (31) [[[17,5675958815995]]]
11, 2.4, (31) [[[1,66920656116909]]]
8, 2.0, (156) [[[17,2896275923337]]]
11, 2.4, (31) [[[1,68066053087753]]]
5, 5.0, (32) [[[17,2653228273426]]]
12, 3.0, (32) [[[1,64769544732641]]]
10, 1.0, (31) [[[17,3164466433583]]]
12, 3.0, (31) [[[1,63791766830701]]]
11, 2.0, (31) [[[17,6148085860074]]]
12, 3.8, (94) [[[2,05081930804055]]]
11, 2.0, (31) [[[17,2871133063001]]]
8, 2.4, (63) [[[1,73765101430489]]]
12, 3.0, (32) [[[15,6251702381169]]]
6, 6.64, (32) [[[1,66585417979101]]]
12, 3.8, (31) [[[17,2873926714149]]]
11, 2.0, (31) [[[1,65887005192001]]]
12, 3.8, (187) [[[17,2899069574485]]]

tra le quadre il dato che mi interessa ed è il ritardo di esecuzione tra 3 thread

misterx
25-07-2011, 22:15
ho fatto anch'io delle prove basandomi su questo: http://www.hwupgrade.it/forum/archive/index.php/t-2318460.html ma tra clock() suggerito e QueryPerformanceCounter() vi sono differenze sostanziali

misterx
26-07-2011, 12:14
ho risolto

misterx
28-07-2011, 22:08
provo a chiedere lo stesso, magari qualcuno lo sa :)

Se aveste due thread, uno che produce numeri casuali riempiendo un array ampio 128 byte ogni 500 ms e ne aveste un altro che cerca di determinare attraverso un ciclo da 0 a 127 ad esempio quando il bit 3 del byte 30 passa da 0 a 1, che tempistiche vi aspettereste in termini di esecuzione pura tra istruzioni?

misterx
29-07-2011, 12:59
il dubbio è questo cioè devo determinare in modo preciso il tempo ciclo tra produttore e scrittore

//thread produttore
while(1)
{
WaitForSingleObject(hMutex,INFINITE);

for(int i=0; i< 128; i++) {buf[i]=rand(); }

t1=StartCounter();

ReleaseMutex(hMutex);

Sleep(20);
}


//thread consumatore
while(1)
{
WaitForSingleObject(hMutex,INFINITE);

for(int i=0; i< 128; i++)
{
stato[i]=( buf[comp[i]] & (int)pow(2,nbit[i]) );

if( stato[i] != oldstato[i])
sprintf(miobuf, "%d.%d, 1, %d",.......);


SetEvent ( hEvent );

ReleaseMutex(hMutex);
}

Sleep(20);
}


//thread scrittore
while(1)
{
WaitForSingleObject ( hEvent , INFINITE );

fprintf(cp,"%d, %s, %lf\n",...........);

t2=StopCounter()

ResetEvent(hEvent);
}