Limiti per le raccolte senza blocco?


10

David Rodríguez - dribeas ha scritto in un commento su StackOverflow che "Non tutte le raccolte possono essere implementate senza blocchi". Non sono sicuro che sia vero e non riesco a trovare la prova in entrambi i casi.

Questa affermazione non è molto precisa, ma lasciami provare a riformularla in un modo leggermente più formale: per ogni tipo di raccolta C, esiste un tipo di raccolta senza blocco CLF che offre lo stesso insieme di operazioni e in cui ogni operazione su CLF ha la stessa complessità big-O dell'operazione corrispondente su C.

Non mi aspetto una trasformazione, comunque.


1
Come non esperto, mi chiedo se "senza serratura" possa essere rigorosamente definito.
Tsuyoshi Ito,

1
@Suresh: forse un sinonimo di "struttura dei dati"?
Tsuyoshi Ito,

2
Cosa succede se si prende semplicemente un'implementazione senza blocco di STM (memoria transazionale del software) e si implementa qualsiasi struttura di dati?
Jukka Suomela,

5
@Tsuyoshi: penso che non ci sia una definizione formale di lock-free. Informalmente, significa che non usi l'istruzione LOCK della CPU, che è lenta, e segui il confronto e lo scambio più veloci. Poiché un LOCK può essere simulato con il confronto e lo scambio, è difficile stabilire un limite netto tra "si utilizza essenzialmente il confronto e lo scambio qui per simulare un blocco (o una transazione per quella materia)" e "oh, questo è un uso davvero intelligente di confronta-e-scambia e non sembra affatto simulare un'operazione di livello superiore di cui siamo a conoscenza. "
Radu GRIGore,

1
Per quanto ne capisco, qui il blocco senza blocco è sinonimo di non blocco. Ciò non implica le LOCKistruzioni della CPU ma lo scheduler dei thread, tramite mutex / semafori / ecc.
MSalters il

Risposte:


11

Dato che ero un po 'confuso, comincio chiarendo alcuni concetti nella domanda.

Raccolta . Non vedo alcun motivo per dedicare del tempo a definire rigorosamente cosa significa "raccolta" quando possiamo semplicemente chiedere cosa succede per le strutture di dati in generale. Una struttura di dati occupa un pezzo di memoria e ha alcune operazioni che possono accedere a tale memoria e che possono essere invocate dagli utenti . Questi utenti possono essere processori distinti o semplicemente thread diversi, non ci riguardano. Tutto ciò che conta è che possano eseguire operazioni in parallelo.

Senza serratura . Herlihy e Boss affermano che una struttura di dati è priva di blocchi quando un utente in crash non impedisce ulteriori usi della struttura di dati. Ad esempio, immagina di versare acqua su un processore che si trova nel mezzo dell'inserimento di un nodo in un set ordinato. Bene, se altri processori tentano successivamente di inserirsi in quel set ordinato, dovrebbero riuscire. ( Edit: Secondo questa definizione, è il caso che se utilizza una struttura dati serrature, allora non è-serratura libera, ma è non il caso che se una struttura di dati non utilizza serrature allora è senza blocchi.)

Con queste definizioni, penso che Herlihy e Boss sostengano sostanzialmente che la risposta è trasformare le regioni critiche in transazioni.

Ma, potresti chiedere, ha la stessa complessità? Non sono sicuro che la domanda abbia un senso. Prendere in considerazione push(x) { lock(); stack[size++] = x; unlock(); }. È un'operazione a tempo costante? Se si ignora l'operazione di blocco e quindi altri utenti, è possibile rispondere SÌ. Se non desideri ignorare altri utenti, non c'è davvero modo di dire se push verrà eseguito a tempo costante. Se salite di un livello e vedete come lo stack viene utilizzato da un determinato algoritmo, allora potreste essere in grado di dire che push richiederà sempre tempo costante (misurato ora in termini di qualunque cosa accada sia l'input del vostro algoritmo parallelo). Ma questa è davvero una proprietà del tuo algoritmo, quindi non ha senso dire che push è un'operazione a tempo costante.

In breve, se si ignora quanto un utente che esegue un'operazione attende altri utenti, l'utilizzo delle transazioni anziché delle aree critiche risponde affermativamente alla domanda. Se non si ignora il tempo di attesa, è necessario esaminare come viene utilizzata la struttura dei dati.


Non sono troppo sicuro che si possa effettivamente considerare che l' pushoperazione come indicato sopra non è un'operazione a tempo costante. Per un numero fisso di processori e un'implementazione comune di lockciò non garantisce la mancanza di fame, l'operazione sopra descritta (nel caso peggiore, per un dato processore prende N_proc * O (1), che può essere ingenuamente considerato O (1) ( numero di processori inclusi nella costante nascosta)
David Rodríguez - dribeas

nf(n)f

Bene, l'accesso alla memoria è un caso comune. La maggior parte delle analisi dell'algoritmo presuppone che l'accesso alla memoria sia O (1) indipendente dalla memoria utilizzata; le architetture di memoria reale (con cache ecc.) sono meglio approssimate da O (log N) dove N è la memoria utilizzata.
MSalters il

Mentre il presupposto che il numero di processori sia una costante è abbastanza pratico, lo eviterò. Quindi il problema è che la complessità non può essere analizzata in modo unidimensionale, poiché la dimensione del problema è destinata a crescere sia nella dimensione dell'input che nel numero di processori, entrambi i quali sono dimensioni ortogonali. Supponendo che un particolare contenitore nella libreria standard C ++ (ovviamente ne scelga uno difficile) uno dei requisiti è che tutti gli elementi sono contenuti in un blocco contiguo di memoria.
David Rodríguez - dribeas,

Ora, aggiungere un elemento al vettore è un'operazione di tempo costante ammortizzata (se non si adatta al blocco precedentemente allocato, la chiamata impiegherà un tempo lineare sul numero di elementi nel contenitore, ma se il blocco di memoria riservato è acquisito seguendo una sequenza esponenziale il costo ammortizzato è costante). Se si implementa un contenitore thread-safe, si bloccherebbe e quindi si eseguirà la modifica, il costo dell'operazione è proporzionale al costo del blocco, cosa che non so davvero ... ma in una prima approssimazione si può considerare principalmente costante
David Rodríguez - dribeas,

3

Penso che "COLLEZIONI" sta per "code, pile, elenchi collegati, alberi, ..."

Da http://www.cl.cam.ac.uk/research/srg/netos/lock-free/

Attraverso un'attenta progettazione e implementazione è possibile costruire strutture di dati sicure per un uso simultaneo senza la necessità di gestire blocchi o thread di blocchi. Queste strutture di dati non bloccanti possono aumentare le prestazioni consentendo una maggiore concorrenza e possono migliorare la solidità evitando alcuni dei problemi causati dall'inversione di priorità nelle impostazioni locali o errori della macchina e dei collegamenti nei sistemi distribuiti.

La migliore introduzione generale ai nostri algoritmi non bloccanti è il documento Programmazione concorrente senza blocchi, attualmente in fase di invio, che copre i nostri progetti per la memoria transazionale software multi-word comparabile e swap, basata su parole e memoria transazionale basata su oggetti.

Se "lock-free" significa "non usare i semafori, i mutex, i monitor del sistema operarting", allora penso (ma non sono un esperto) che ogni collezione può essere realizzata senza lock usando atomic read-write- modificare le primitive che devono essere supportate dall'hardware.

O()

La documentazione esaustiva sull'argomento è disponibile online:

http://www.google.it/search?q=lock+free+algorithm+filetype%3Apdf

(... e ulteriori riferimenti alla fine di ogni documento)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.