PDA

View Full Version : memoria condivisa - devo flushare?


71104
14-05-2007, 20:24
parlando sia di Linux che di Windows, se utilizzo un file mappato per creare una zona di memoria condivisa tra processi, oltre a dovermi sincronizzare con mutex e quant'altro per mantenere la consistenza dei dati condivisi devo anche flushare la cache del processore in un ambiente multicore? o ci pensa in qualche modo già l'architettura hardware in maniera a me trasparente?

per ragionare in termini pratici: mettiamo che sono su Windows e ho un file mappato creato come parte del file di swap (una pura area di memoria condivisa insomma); e mettiamo che nella zona di memoria condivisa ho una lista (e i link della lista sono espressi come offset anziché come puntatori perché la zona di memoria può essere mappata ad indirizzi diversi in processi diversi, ma vabbè). inoltre ho anche un mutex su cui un processo deve bloccarsi quando vuole aggiungere o togliere nodi; prima di rilasciare il mutex il processo deve anche assicurarsi che i cambiamenti siano andati in memoria fisica flushando la cache del core su cui ha lavorato?

71104
14-05-2007, 20:26
ah, ed inoltre dovrei dichiarare i nodi della lista come volatile per impedire al compilatore di ottimizzare cachandoli nei registri, giusto?

cionci
14-05-2007, 20:44
prima di rilasciare il mutex il processo deve anche assicurarsi che i cambiamenti siano andati in memoria fisica flushando la cache del core su cui ha lavorato?
Che io sappia no. In u ambiente SMP ci sono algoritmi per la cache snoop delle altre CPU che dovrebbero evidenziare la presenza dal dato in cache...se il thread/processo invece termina il suo time slice, la cache viene automaticamente flushata e quindi le locazioni modificate vengono scritte in memoria.

-fidel-
14-05-2007, 21:01
parlando sia di Linux che di Windows, se utilizzo un file mappato per creare una zona di memoria condivisa tra processi, oltre a dovermi sincronizzare con mutex e quant'altro per mantenere la consistenza dei dati condivisi devo anche flushare la cache del processore in un ambiente multicore? o ci pensa in qualche modo già l'architettura hardware in maniera a me trasparente?

Confermando quanto detto da cionci, sì, se ne occupa l'hardware / il kernel (almeno, ti parlo di kernel Linux, ma non credo che con Win Vista la situazione sia troppo diversa).
Comunque non afferro il problema...

-fidel-
14-05-2007, 21:04
ah, ed inoltre dovrei dichiarare i nodi della lista come volatile per impedire al compilatore di ottimizzare cachandoli nei registri, giusto?

Se non vuoi che il compilatore faccia "ipotesi" su quelle variabili quindi fare cache o "predizioni" sui valori, sì.
Però, come prima, mi sa che mi sono perso qualcosa sul fine ultimo del tutto...

cionci
14-05-2007, 21:04
Il problema a cui si riferiva è che essendo i dati in cache non ancora scritti, un eventuale secondo processore avrebbe trovato dati non aggiornati in memoria centrale ;)

-fidel-
14-05-2007, 21:05
Il problema a cui si riferiva è che essendo i dati in cache non ancora scritti, un eventuale secondo processore avrebbe trovato dati non aggiornati in memoria centrale ;)

Ah, beh ma se dovessimo preoccuparci di questo saremmo proprio a posto :)
Meglio che lavorino alla Intel/AMD :D

71104
14-05-2007, 21:08
Il problema a cui si riferiva è che essendo i dati in cache non ancora scritti, un eventuale secondo processore avrebbe trovato dati non aggiornati in memoria centrale ;) esatto, e nel caso di una lista doppiamente linkata "dati non aggiornati" potrebbe voler dire "inconsistenti" (es. un nodo punta al successivo come successore, il quale però punta due nodi addietro come predecessore). senza contare che se il flush (che sia dei registri o della cache) avvenisse in un momento non ben definito in cui il mutex non è bloccato, altri processi di fatto osserverebbero dei cambiamenti in un momento in cui il mutex appunto non è bloccato da chi li ha fatti.

71104
14-05-2007, 21:08
cmq grazie cionci; non me ne devo preoccupare dunque, mi basta volatile.

71104
14-05-2007, 21:11
Ah, beh ma se dovessimo preoccuparci di questo saremmo proprio a posto :) però intanto di dichiarare i nodi come volatili me ne sono dovuto preoccupare :read:
le cose non sono del tutto trasparenti :Prrr: anche se in realtà in questo caso sarebbe un problema del compilatore e non dell'architettura.

cionci
14-05-2007, 21:12
altri processi di fatto osserverebbero dei cambiamenti in un momento in cui il mutex appunto non è bloccato da chi li ha fatti.
Se succede significa che hai gestito male la mutua esclusione...quando rilasci la mutua esclusione i dati devono essere consistenti.

-fidel-
14-05-2007, 21:16
però intanto di dichiarare i nodi come volatili me ne sono dovuto preoccupare :read:

Perchè? Per lo meno, "volatile" la si usa normalmente in ambiente multithread/multiprocesso (affinche il compilatore eviti race conditions al posto tuo :)) ma in ambiente multiprocessore il tutto è lasciato all'hardware.
Fai bene a dichiarare i nodi come "volatile" ma non a causa un ambiente multiprocessore, ma di multithreading (comunque se usi una sezione critica fatta bene puoi anche evitare, non se4rve a nulla visto che da quel punto di vista non hai race conditions).

71104
14-05-2007, 21:26
Se succede significa che hai gestito male la mutua esclusione...quando rilasci la mutua esclusione i dati devono essere consistenti. non è detto che il flush avvenga prima del rilascio del mutex e non penso che sia possibile assumere che il flush di una locazione (ad es. quella di uno dei due link del nodo) implichi il flush di un'altra (quella dell'altro link). sequenza cronologica delle operazioni:
1) i due link vengono scritti nei registri; da questo momento il mutex per quanto ne so io (che non sono a conoscenza delle ottimizzazioni operate dal compilatore e dell'uso che fa dei registri) può essere rilasciato
2) il link al nodo precedente viene messo in memoria fisica
3) viene rilasciato il mutex
4) un thread che gira su un altro processore blocca il mutex e vede i dati inconsistenti
5) l'altro link viene messo in memoria fisica

quindi ciò che mi preme è che prima del rilascio del mutex tutto sia completamente flushato. visto che l'hardware mi rende la cache trasparente, io mi preoccupo solo dei registri, quindi uso volatile.

cionci
14-05-2007, 21:36
Mi sembra che tu ti stia facendo problemi inutili...stai programmando ad alto livello...a tutto il resto ci pensa l'hardware e il compilatore...

- acquisisci la mutex
- lavori sulla memoria condivisa
- rilasci la mutex quando la memoria condivisa è in uno stato consistente

Basta, te non devi pensare ad altro...se fai altre supposizioni sei fuori strada perché c'è il rischio che il tuo codice non funzioni su tutte le architetture

recoil
14-05-2007, 22:24
Mi sembra che tu ti stia facendo problemi inutili...stai programmando ad alto livello...a tutto il resto ci pensa l'hardware e il compilatore...

- acquisisci la mutex
- lavori sulla memoria condivisa
- rilasci la mutex quando la memoria condivisa è in uno stato consistente

Basta, te non devi pensare ad altro...se fai altre supposizioni sei fuori strada perché c'è il rischio che il tuo codice non funzioni su tutte le architetture

esattamente ;)

71104
15-05-2007, 00:20
se il problema è reale io ci penso :O

anche perché sennò il prof mi chiede come mai non ho usato volatile per dichiarare dei dati usati da thread diversi, che quello è pignolo è :read:

71104
15-05-2007, 00:21
e poi programmo ad alto livello per modo di dire: sto usando il C... :huh: :D
pensate che devo scrivere #ifndef __MACRO__, #define __MACRO__ all'inizio di ogni header, e ovviamente l'#endif alla fine :asd:

71104
15-05-2007, 00:23
e poi programmo ad alto livello per modo di dire: sto usando il C... :huh: :D a-ehm, ci tengo a precisare che questa frase NON voleva significare "sto usando il CULO :huh:" :D :D :D
no perché poteva essere :D :D :D

recoil
15-05-2007, 00:24
e poi programmo ad alto livello per modo di dire: sto usando il C... :huh: :D
pensate che devo scrivere #ifndef __MACRO__, #define __MACRO__ all'inizio di ogni header, e ovviamente l'#endif alla fine :asd:

è una buonissima abitudine :)

71104
15-05-2007, 00:29
è una buonissima abitudine :) si, solo che è un'abitudine trogloditica, come il resto di quel linguaggio :huh:
sono abituato al sistema di packaging di Java :O

e poi meno male che uso C99, sennò mi toccava pure dichiarare tutte le variabili all'inizio e dovevo rinunciare a const e alle variabili dichiarate nelle intestazioni dei for.

-fidel-
15-05-2007, 08:16
Mi autoquoto:

Ah, beh ma se dovessimo preoccuparci di questo saremmo proprio a posto :)
Meglio che lavorino alla Intel/AMD :D

Per ribadire che, appunto, sono problemi che non si pongono, fa tutto l'hardware. Tu preoccupati della concorrenza dei thread/processi, e attento alla starvation con la sezione critica ;)
Ribadisco, inoltre, che con unasezione critica ben fatta, i membri "volatile" sono inutili (mentre, come detto, non c'entrano niente con robe tipo cache della CPU, visto che quella non la gestisci tu (non gestisci neanche il fuzionamento della memoria centrale se è per questo :D))

cionci
15-05-2007, 09:01
Oddio il volatile volendo è l'unica cosa che c'entra...
Comunque in teoria dopo la fine della sezione critica le variabili condivise non dovresti più usarle direttamente, quindi il compilatore può usare tutte le ottimizzazioni che vuoi, ma all'ultimo uso della variabile condivisa nella sezione critica il compilatore andrà a metterla ad ogni costo in memoria prima della chiusura della sezione.
Te mi dirai, e se c'è un ciclo che cicla sulla sezione critica ? A quanto mi risulta quando interviene il branch predictor il compilatore dovrebbe aver scaricato in memoria le variabili (non presenti nella gestione del ciclo) che ha sui registri...in teoria potrebbe anche non farlo e farlo dopo la fine del ciclo, ma vedo un ottimizzazione di questo tipo un po' troppo spinta.

-fidel-
15-05-2007, 09:26
Oddio il volatile volendo è l'unica cosa che c'entra...

Volendo... Non a caso avevo scritto in un precedente post:

Fai bene a dichiarare i nodi come "volatile" ma non a causa un ambiente multiprocessore, ma di multithreading (comunque se usi una sezione critica fatta bene puoi anche evitare, non serve a nulla visto che da quel punto di vista non hai race conditions).


Poi, appunto, dipende da come è implementata la sezione critica ;)
Questo perchè, essendo possibile evitare di usare "volatile" con la sezione critica, lo svantaggio è una maggiore attenzione in fase di programmazione, ma il vantaggio è una maggiore performance del programma.
Con volatile, non hai problemi in fase di programmazione, ma lo svantaggio è una perdita di prestazioni (che si fa considerevole all'aumentare della dimensione del pool di dati).

EDIT: comunque ribadisco una cosa: all'interno della sezione critica, il programma si comporta come un programma single thread, quindi volatile è inutile. volatile può essere usato sul mutex stesso (dipende da come implementi il mutex).
Magari non si capiva prima (problemi terminologici mutex/sezione critica...), comunque se l'accesso al pool di dati avviene in sezione critica, volatile non ha senso. Volatile la uso sul mutex che regola l'accesso alla sezione critica (implementando una classe mutex o un semaforo manualmente ad esempio).

EDIT 2: Ah, non sto considerando comunque l'eventuale uso, in ambiente windows, di oggetti kernel per le critical sections... Parlo sempre di implementazione del concetto di sezione critica (usando quindi meccanismi definiti dal programmatore, che ricalcano la teoria, ad esempio creare una classe mutex che va bene su qalunque SO). Questo perchè, se non ricordo male, l'implementazione MS dell'oggetto kernel mutex è già "volatile".

^TiGeRShArK^
15-05-2007, 09:40
Volendo... Non a caso avevo scritto in un precedente post:


Poi, appunto, dipende da come è implementata la sezione critica ;)
Questo perchè, essendo possibile evitare di usare "volatile" con la sezione critica, lo svantaggio è una maggiore attenzione in fase di programmazione, ma il vantaggio è una maggiore performance del programma.
Con volatile, non hai problemi in fase di programmazione, ma lo svantaggio è una perdita di prestazioni (che si fa considerevole all'aumentare della dimensione del pool di dati).

EDIT: comunque ribadisco una cosa: all'interno della sezione critica, il programma si comporta come un programma single thread, quindi volatile è inutile. volatile può essere usato sul mutex stesso (dipende da come implementi il mutex).
Magari non si capiva prima (problemi terminologici mutex/sezione critica...), comunque se l'accesso al pool di dati avviene in sezione critica, volatile non ha senso. Volatile la uso sul mutex che regola l'accesso alla sezione critica (implementando una classe mutex o un semaforo manualmente ad esempio).

EDIT 2: Ah, non sto considerando comunque l'eventuale uso, in ambiente windows, di oggetti kernel per le critical sections... Parlo sempre di implementazione del concetto di sezione critica (usando quindi meccanismi definiti dal programmatore, che ricalcano la teoria, ad esempio creare una classe mutex che va bene su qalunque SO).
appunto ;)
quello è l'uso principe delle volatile :p

-fidel-
15-05-2007, 10:34
@Tigershark

Come stai messo a programmazione OpenGL in C/C++?