Stáhnout prezentaci
Prezentace se nahrává, počkejte prosím
1
Binární vyhledávání v poli metodou půlení intervalu
Binární vyhledávání v seřazeném poli metodou půlení intervalu má stejně jako vyhledávání v binárním stromu logaritmickou složitost (log2N), výhodou je jednodušší adresování – není potřeba pracovat s ukazateli, stačí indexace. Princip: vyhledávání začíná v půlce vzestupně seřazeného pole, pokud je hledaný klíč menší než hodnota na tomto indexu, hledání pokračuje v levé půlce pole, jinak v pravé půlce pole, atd. Příklad: hledáme číslo 3 1. krok: Pole[N div 2] =5 a to je > 3, jdeme na levou půlku 2. krok: Pole[(N div 2) div 2] = 2 a to je < 3, jdeme na půlku intervalu indexů 3..4 3. krok: Pole[3]=3 a to je = hledanému klíči = KONEC 1 2 3 4 5 8 10 13 15
2
Binární vyhledávání v poli metodou půlení intervalu
Function Search(pole:array[1..N] of tKey; key:tKey): boolean var D=N div 2; I:=D; begin while (D>0) and (pole[I]<>key) do begin D:=D div 2; if key<pole[I] then I:=I-D else I:=I+D; end; Search:=pole[I]=key; End;
3
ADT Tabulka ADT tabulka (v české terminologii také „tabulka s rozptýlenými položkami“) implementuje tzv. asociativní pole, tj. pole, které nemusí být nutně indexováno pouze ordinálním datovým typem (např. Pole[3]=OBSAH), ale jakýmkoli typem (např. Pole[“Franta Šiška”]=OBSAH ADT tabulka lze implementovat téměř čímkoli – nejčastější implementace jsou založeny na použití statických polí ve spojení s hashovací funkcí, nebo používají AVL stromy Dobře implementovaná hash tabulka vyhledává ještě rychleji než AVL strom ADT Tabulka proto najde uplatnění všude tam, kde potřebujeme rychle vyhledávat podle hodnoty klíče – např. řídící algoritmy keší, filesystémů, tabulky symbolů v překladačích, …
4
ADT Tabulka s přímým přístupem
je-li známá množina všech klíčů K=[K1,…,KN], které se budou v tabulce používat, a je-li možné najít jedno-jednoznačnou mapovací funkci f(Ki)=i (pro i=1,2,…N) pro všechny prvky množiny K, je možné vytvořit tabulku s přímým přístupem. Příklad: množina všech klíčů K=['Josef', 'Hana', 'Prokop', 'Adela'], mapovací funkce f(K)=['Josef‘→1, 'Hana‘→2, 'Prokop'→3, 'Adela'→4] pro takovouto množinu s jednoznačnou mapovací funkci bude implementace metod ADT Tabulka jednoduchá: type tTabulka=array [1..N] of record data:tData; obsazen:boolean; end; tKlic=string; procedure InsertTab(var Tab: tTabulka, k:tKlic, data:tData); begin Tab[f(k)].data:=data; Tab[f(k)].obsazen:=true; end; function SearchTab(var Tab: tTabulka, k:tKlic, var data:tData); begin if Tab[f(k)].obsazen then begin data:= Tab[f(k)].data; SearchTab:=true; end else SearchTab:=false; end;
5
Tabulka ve funkci cache
ADT Tabulka se hodí i pro realizaci v HW - např. cache pro přístup do paměti nebo cache harddisku jsou realizovány jako tabulky, kde množina klíčů K=všechny možné adresy v paměti RAM, f(K)= funkce, mapující adresu paměti RAM na index kešovaného bloku paměti v rámci cache protože velikost RAM (=počet klíčů) je mnohem větší než velikost cache (=rozsah tabulky), nemůže být mapovací funkce jedno-jednoznačná = některé adresy v RAM se namapují na stejnou adresu v cache= „cache miss“ CPU Cache RAM, HDD X GHz X GHz Y MHz
6
Tematický odskok: Implementace cache
Úspěšnost keše závisí na 2 faktorech: velikost keše - čím větší, tím lepší. Velká keš je ale drahá (keš procesoru zabírá na čipu až 50% místa) chytrost mapovací funkce - měla by se chovat tak, aby průměrný program při svém běhu potřeboval minimum přístupů do RAM. Mapovací fce tedy musí zohledňovat statistické chování průměrného programu. Přitom ale tato fce musí být tak jednoduchá, aby šla vyhodnoti v jediném taktu procesoru a nezabrala na čipu zbytečně velkou plochu! strategie zápisu do cache (FIFO, Last recently used, Least frequently used) a do RAM (write-through, write back)
7
Příklady mapovacích funkcí cache
Přímé mapování: příklad máme cache 512k x 8bitů. Paměť RAM má 512 MB, adresa je 32bitová, data 8bitové. předpoklad: programy tráví 90% času vykonáváním smyček, jejichž kód se vejde do 4kB paměti. Většina dat je také v souvislých oblastech paměti, 90% proměnných je < 4kB. rozdělíme si cache na 128 bloků o velikosti 4kB (4096 bajtů) dolních 12bitů adresy (A0..A11) bude reprezentovat adresu v rámci bloku, 7 bitů (A12..A18) budou adresovat 128 bloků cache. Příklady: Adresa $1FA1 se namapuje na blok s indexem 1, adresa uvnitř bloku bude $FA1. Adresa $7F8AC se namapuje na blok s indexem $7F (=127 aneb poslední blok), adresa uvnitř bloku bude $8AC Bity A18..A31 musíme ošetřit tak, aby cache rozlišovala mezi adresami např. $FFF8XXXX a $0000XXXX
8
Přímé mapování v cache Cache
bity A18..A31 připojíme ke každému bloku tak, abychom věděli, do které oblasti paměti blok v cache patří pokud budou v cache v bloku X uloženy data z adresy např. $FFF00001 a program bude přistupovat na adresu $ (stejný blok, stejná adresa v bloku, ale jiná adresa v paměti RAM), vyhodnotíme toto jako „cache miss“ CPU RAM A0..A11 blok 127 A19..A31 ... A12..A18 A0..A31 blok 1 A19..A31 blok 0 A19..A31 Cache
9
Asociativní cache Přímé mapování je velmi jednoduché a levné
nevýhoda=určité adresy v RAM se mapují vždy pouze na jednu určitou adresu v cache. Pokud určitý program bude přistupovat pouze na adresy od adresy , pak zabere 2 bloky cache, ale obě budou využité pouze z poloviny! Přímé mapování adres v cache se také nehodí pro počítače s OS a s podporou multitaskingu, kde běží zároveň mnoho procesů OS a dalších uživatelských programů a, které navíc velmi často volají rozsáhlé funkce OS. Všechny tyto programy pak využívají adresy různých oblastí paměti, které se budou často mapovat na stejné bloky cache - nízká účinnost cache ! Ideální stav = plně asociativní cache = blok paměti RAM se může uložit na jakoukoli (nejbližší volnou) adresu v cache - mapovací funkce v takovémto případě ale bude tak složitá, že ji na HW úrovni v podstatě nelze rozumně realizovat Proto musíme volit kompromis - princip “N-way set associative cache” (např. Pentium = 2 way associative cache, od P MMX = 4 way associative cache), což je v podstatě hash tabulka s omezením počtu synonym na N
10
Tabulka se zřetězenými synonymy
Pokud není mapovací funkce jedno-jednoznačná (což většinou není), musíme řešit problém, jak uložit klíče, u nichž mapovací funkce vrací stejnou hodnotu indexu. Řešení = použijeme implicitní nebo explicitní řetězení synonym Explicitní řetězení = použití ukazatelů: k1 k2 F(k1) F(k2) pole
11
Hash tabulka se zřetězenými synonymy
Type tUkPrvek=^tPrvek; tPrvek=record data:tData; key:tKey; ukDalsi:tUkPrvek; End; tTable=array[1..N] of tPrvek; function HTSearch (var Table : tHTable; Key : tKey; var ukPrvek:tUkPrvek) : boolean; begin UkPrvek :=Table[Rozptyl(Key)]; {Nastav ukazatel na první ze synonym} HTSearch:=false; if ukPrvek<>nil then while (ukPrvek ^.ukDalsi<>nil) and (ukPrvek^.Key<>Key) do UkPrvek := UkPrvek ^.ukDalsi; {prohledávej seznam synonym dokud nedojdeš} HTSearch:= UkPrvek ^.Key=Key; {na konec nebo nenajdeš hledané} end; function Rozptyl (var Key:tKey) : integer; var i : integer; Result : integer; begin Result:=1; for i:=1 to length(Key) do Result:=Result+ord(Key[i]); Rozptyl := (Result mod HTSize)+1; end;
12
Hash tabulka se zřetězenými synonymy
Nevýhoda explicitně zřetězených synonym = lineární přístup (vyhledávání v rámci synonym má složitost N) a paměťová režie navíc (každý prvek tabulky obsahuje ukazatel). Alternativa = hash tabulka s implicitně zřetězenými synonymy, ve které jsou klíče se stejnou hodnotou uloženy na dalších indexech tabulky Indexy pro uložení synonym mohou být získány zvyšováním původního indexu o jedničku do chvíle, než je najdeno první volné místo v tabulce – dobré pouze pro řídce obsazené tabulky Zvyšováním původního indexu pomocí nějaké další funkce (nejčastěji kvadraticky) Pomocí druhé mapovací funkce (nejčastější případ)
Podobné prezentace
© 2024 SlidePlayer.cz Inc.
All rights reserved.