m / 2

annuncio pubblicitario
B­alberi
dizionari in memoria secondaria
dizionari su memoria secondaria
• la memorizzazione su memoria secondaria risponde a due esigenze
– permanenza dell’informazione
• la RAM è volatile
– grande quantità di dati
• la RAM è limitata
• memoria secondaria: disco
ASD ­ B­tree
2
modello di costo
• il costo in termini di tempo per accedere al disco (scrittura/lettura) domina in maniera sostanziale il costo di elaborazione in RAM
– parti meccaniche in movimento con costanti di tempo dell’ordine delle decine di millisecondi
– una CPU esegue un’istruzione elementare in pochi colpi di clock
– ad es., copia di un dato dalla RAM a un registro
• supp. 10 colpi di clock, CPU a 1GHz
• 10 ns per copia RAM­>registro
• 20 ns per un’assegnazione
ASD ­ B­tree
3
modello di costo/2
• Occorre considerare modelli di costo diversi dal modello RAM se il costo dominante della computazione è costituito dagli accessi in memoria secondaria.
• Ex: # di accessi a disco x seek time + tempo di trasferimento dei dati da disco a memoria principale ASD ­ B­tree
4
modello di costo/3
• l’accesso al disco avviene per blocchi (o pagine fisiche )
cilindro
faccia
– tutti i blocchi hanno la stessa dimensione (da 512B ad alcuni KB)
– ciascun blocco è definito da tre coordinate: cilindro (o traccia ), settore, faccia
traccia
ASD ­ B­tree
settore
5
modello di costo/4
• tempo di accesso al disco = somma di tre componenti
– seek time
• per posizionare la testina sul cilindro corretto
– latency time
• attesa necessaria affinché il settore desiderato transiti sotto la testina
– tempo di trasferimento
• dati scambiati fra RAM e disco
ASD ­ B­tree
6
esempio
• seek time
– ~15­20ms
• latency time
– valore atteso: 50% del tempo di rotazione
• in un disco a 7200rpm, poco più di 4ms
• tempo di trasferimento
– velocità: alcuni MB/s
• blocco di 4KB, seek 15 ms, 10000rpm, velocità di trasferimento 2MB/s
• tempo (ms) di accesso al blocco ≈ 15 + 3 + 2 ms/blocco = 20ms/blocco
• costo (ammortizzato) per byte ≈ 20ms/4096B ≈ 4.9µs/B ASD ­ B­tree
7
esempio/2
• nel caso di accesso a più blocchi contigui vengono pagati un solo seek e un solo latency
• la convenienza aumenta all’aumentare del numero di blocchi contigui
– “bulk access” vs. ”random access”
• blocco di 4KB, seek 15 ms, 10000rpm, velocità di trasferimento 2MB/s
• tempo (ms) di accesso a due blocchi contigui ≈ 15 + 3 + 2∙2 ms/blocco = 22ms/blocco
• costo (ammortizzato) per byte ≈ 22ms/8192B ≈ 2.7µs/B ASD ­ B­tree
8
esempio/3
tempo accesso (ms)
120,00
100,00
ms
80,00
60,00
40,00
20,00
0,00
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
#blocchi contigui
ASD ­ B­tree
9
ammortizzazione
la contiguità premia
tempo (microsec.) ammortizato per byte
6000,00
microsec.
5000,00
4000,00
3000,00
2000,00
1000,00
0,00
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
#blocchi contigui
ASD ­ B­tree
10
modello di costo/5
• costo (tempo): # di I/O su disco
– blocco ha dimensione B
– RAM ha dimensione M – disco ha dimensione ∞
• tempo di CPU trascurabile
– buona approssimazione in molti casi
ASD ­ B­tree
11
dizionari in memoria secondaria
idea: paginare un albero di ricerca
54
22
77
11
4
1
37
17
8
28
64
46
60
86
70
80
91
13 19 24 35 40 51 58 62 67 74 78 83 88 98
ASD ­ B­tree
12
BST paginato
• l’albero non è più binario
• si può definire un albero di ricerca m ­ario?
ASD ­ B­tree
13
B­tree di ordine m
• radice con 0 o p > 1 figli
• ogni nodo interno (non radice) con k – 1 chiavi e k figli, m /2  k  m
– non lo stesso k per ciascun nodo!
• foglie con k­1 chiavi, m /2  k  m
• albero di ricerca
– ad ogni chiave è associato un sottoalbero destro di chiavi inferiori ed uno sinistro di chiavi superiori
• m è il max numero di figli
• Nota: le foglie contengono puntatori a blocchi di elementi
ASD ­ B­tree
14
B­tree di ordine 4
56
22 41
2
14
26 34
66 87
44 46 51
59 61
71 77
90 92 98 /
Nota: si sono indicate solo le chiavi
è anche un B­tree di ordine 3?
ASD ­ B­tree
15
scelte progettuali
•
•
•
•
•
un nodo = un blocco
chiave c bit
riferimento a sottoalbero r bit
in ogni nodo rm + c (m ­ 1) bit
m = (B + c )/(r + c )
– se B = 4KB, c = r = 32 bit
m ≈ 64
• Ogni blocco di elementi è memorizzato in un blocco su disco (dim. B)
– Se max. L bit per elemento al più B/L elem./blocco
• Obiettivo: avere alberi di altezza piccola (es. 4)
ASD ­ B­tree
16
Altezza di un B­tree
• quali sono le altezze minime e massime di un B­tree di ordine m con n chiavi?
– altezza max ottenuta quando ogni nodo interno ha il min numero di figli (albero spoglio)
• la radice ha 2 figli ed ogni altro nodo interno ha m /2 figli
– altezza min quando ogni nodo interno ha il max numero (m ) di figli (albero frondoso)
ASD ­ B­tree
17
altezza di un B­tree spoglio
• sia q = m /2 • 1 chiave nella radice
• q ­ 1 chiavi in ogni altro nodo
• livello 2: 2 nodi
• livello 3: 2q nodi
• livello 4: 2q 2 nodi
• livello i : 2q i –2 nodi
ASD ­ B­tree
18
altezza di un B­tree spoglio/2
• # chiavi in un B­tree spoglio di altezza h >=
12 q−12 q q−12 q 2  q−1⋯2 q h−2  q−1=
h−2 i
q h−1−1
=12 q−1 ∑i=0 q =12 q−1
=2 q h−1−1=n
q−1
n1
⇒ h=log q
1
p1
p
2
−1
i q
D.: qual è l’altezza di un B­tree frondoso?
∑i=0 q =q−1
ASD ­ B­tree
19
Scelte progettuali/2
•
•
•
•
•
un nodo = un blocco
chiave c bit
riferimento a sottoalbero r bit
in ogni nodo rm + c (m ­ 1) bit
m = (B + c )/(r + c )
– se B = 4KB, c = r = 32 bit
m ≈ 64
– con n = 10ML chiavi h  6 E’ possibile avere alberi con altezza piccola in casi di interesse pratico
– radice spesso mantenuta in RAM
ASD ­ B­tree
20
rappresentazione nodi (RAM)
class BTreeNode {
int m;
boolean leaf; /* true se nodo è foglia */
int keyTally; /* No. di chiavi presenti */
int keys = new int[m-1];
BTreeNode references[] = new BTreeNode[m];
BtreeNode(int key) {…} /* Costruttore */
}
/* Nota: si assumono chiavi intere */
/* keys può essere un array di oggetti
contenenti coppie <chiave. rif. a mem.
secondaria> */
ASD ­ B­tree
21
Rappresentazione con riferimenti
ASD ­ B­tree
22
cenno alla rappresentazione dei nodi su disco
• file a sé stanti, ciascuno di un blocco
– più semplice da realizzare
– i riferimenti ai sottoalberi sono nomi di file
– overhead per il sistema operativo
• tutti in un unico file
– soluzione compatta, ma più complessa
– riferimenti ai sottoalberi
• offset relativi all’inizio di un file (file frammentato, solo accessi random)
• indirizzi assoluti (cilindro+settore+faccia, file non portatili)
ASD ­ B­tree
23
ricerca in un B­tree
public BTreeNode BTReeSearch(int key) {
return BTreeSearch(key, root)
}
protected BTreeNode BTreeSearch(int key, BTreeNode node)
{
if (node != null) {
int i=1;
while ((i<=node.keyTally)&&(node.keys[i-1]< key)) {
i++;
if ((i>node.keyTally) || (node.keys[i-1]>key))
return BTreeSearch(key, nodereferences[i-1];
else return node;
}
else return null;
}
ASD ­ B­tree
24
Ricerca chiave di valore 51
56
22 41
2
14
26 34
66 87
44 46 51
59 61
ASD ­ B­tree
71 77
90 92 98 /
25
inserimento in B­tree
• come nei BST, si effettua una ricerca della chiave da inserire
• si tenta dapprima di inserire la chiave in una foglia (appropriata)
– se la foglia non è piena il processo termina
– se la foglia è piena (ha già m – 1 chiavi) abbiamo una situazione di overflow e possiamo scinderla in due
• la scissione può determinare altre scissioni
ASD ­ B­tree
26
Inserimento in foglia non piena
Un albero B prima (a) e dopo (b) l’inserimento
della chiave 7 in una foglia avente celle disponibili
ASD ­ B­tree
27
Inserimento in foglia piena
Inserimento della chiave 6 in una foglia piena
ASD ­ B­tree
28
gestione degli overflow
• gestione dell’overflow tramite scissione (o divisione o split)
– allocazione di un nuovo nodo (foglia)
– le m chiavi vengono così ripartite:
(m – 1) / 2 nella foglia in overflow, (m – 1) / 2 nella nuova e una (la mediana fra le m ) viene inserita nel genitore per separare le due foglie (nell’esempio, m=5)
• se il genitore va in overflow si usa la stessa tecnica
●
ASD ­ B­tree
29
gestione degli overflow/2
• gli overflow si possono propagare verso l’alto fino a coinvolgere la radice
• se la radice va in overflow questa deve venire scissa ed occorre creare una nuova radice, che conterrà la chiave mediana fra le m coinvolte nell’operazione
– in questo caso l’albero aumenta la propria altezza
• Animazione a http://shell.uriel.net/~mozart/File/btree.html ASD ­ B­tree
30
Inserimento
Algorithm BTreeInsert(k) {
<trova foglia in cui inserire k> /* Sia essa node */
<trova pos. adeguata per k nell’array keys>
if (<nodo non pieno) {
<inserisci k ed incrementa keyTally>
return;
}
else {
<suddividi node in node1 e node2>;
<distribuisci chiavi e rif. equamente tra node1 e node2>
<aggiorna node1.keyTally e node2.keyTally>
<k = ultima chiave in node1>
}
/* Continua prossima slide */
ASD ­ B­tree
31
Inserimento
/* Continua da slide precedente */
if (<node era la radice>) {
<crea nuova radice con figli node1 e node2>
<inserisci k e rif. a node1 e node2 nella radice>
root.keyTally=1;
return;
}
else <genitore di node2 = genitore di node>
}
ASD ­ B­tree
32
costo inserimento
• discesa radice – foglia – O(logm/2 n ) I/O • split
– O(1) I/O (3 o 4)
• #split
– O(logm/2 n )
• costo totale: O(logm/2 n )
ASD ­ B­tree
33
eliminazione da un B­tree
• si effettua una ricerca della chiave da inserire
• se la chiave è in una foglia, la si elimina dalla stessa e si verifica se il numero di chiavi rimanenti sia comunque non inferiore a m / 2 ­ 1 – se rimangono troppe poche chiavi si ha underflow, che richiede una gestione specifica
• se la chiave è in un nodo interno la si sostituisce con il predecessore (o il successore), che è in una foglia, e ci si riconduce al caso precedente
– simile alla tecnica usata nei BST
ASD ­ B­tree
34
Azioni eseguite dopo l’eliminazione del numero 6
ASD ­ B­tree
35
gestione degli underflow
• un nodo in underflow ha m / 2 ­ 2 chiavi
• si tenta dapprima una ridistribuzione delle chiavi fra nodo e un fratello, coinvolgendo la chiave che li separa nel genitore
– occorre un fratello con almeno m / 2 chiavi
• se non è disponibile un fratello per operare la ridistribuzione occorre effettuare la fusione (o merge) fra nodo in underflow e un fratello
– richiede una gestione specifica
ASD ­ B­tree
36
fusione di nodi
• due nodi fratelli possono essere fusi se uno di essi è in underflow e l’altro ha il numero di chiavi minimo m / 2 ­ 1
• la fusione consiste nell’inserire in un solo nodo tutte le chiavi presenti nei due nodi, oltre a quella del genitore che separava i due nodi
– la fusione permette di liberare risorse precedentemente allocate a un nodo
– richiede l’eliminazione di una chiave dal genitore, che a sua volta, può andare in underflow, divenendo oggetto di attenzione da parte del gestore dell’underflow
ASD ­ B­tree
37
fusione di nodi/2
• se i nodi oggetto di fusione sono i due unici figli della radice, questa scompare e il risultato della fusione diviene la nuova radice
– in tal caso vengono liberate risorse allocate a due nodi
– l’albero diminuisce l’altezza
• Animazione a http://shell.uriel.net/~mozart/File/btree.
html
ASD ­ B­tree
38
algoritmo di eliminazione
Algorithm BTreeDelete(k) {
node = BTreeSearch(k)
if(node != null) {
if(<node non è foglia>) {
<trova foglia con successore s di k>
<copia s su k in node>
<node = foglia contenente s>
<elimina s da node>
} else <elimina k da node>
ASD ­ B­tree
39
algoritmo di eliminazione/2
while(true) {
if(<node non in underflow>) return;
else if (<c’è un fratello di node con
abbastanza chiavi>) {
<redistribuisci chiavi fra node e fratello>
return;
}
else if (<genitore(node) è radice>) {
if (<radice ha una sola chiave>)
<fondi node, fratello e genitore,
formando nuova radice>
ASD ­ B­tree
40
algoritmo di eliminazione/3
else
<fondi node e suo fratello>
return;
} /* End else if */
else
<fondi node e suo fratello>
<node = genitore(node)>
}
} /* End while */
} /* End if */
} /* End algoritmo */
ASD ­ B­tree
41
costo eliminazione
• discesa radice – foglia – O(logm/2 n ) I/O
• redistribuzione
– O(1) I/O (3 o 4)
• fusione
– O(1) I/O (3 o 4)
• #fusioni
– O(logm/2 n )
• costo totale: O(logm/2 n )
ASD ­ B­tree
42
B+­tree
• chiavi solo nelle foglie
• nodi interni contengono solo informazioni di “branching” e costituiscono un vero e prorpio indice
• le foglie sono collegate orizzontalmente
• algoritmi di gestione simili a quelli per il B­tree
– una differenza notevole è nello split di una foglia: la chiave separatrice viene copiata (e non spostata) nel genitore
ASD ­ B­tree
43
Scarica