External Sorting

64 

Full text

(1)

Katedra informatiky

Tˇr´ıd ˇen´ı na extern´ım ´

uloˇzi ˇsti

External sorting

(2)
(3)

V Ostravˇe 23. ˇcervence 2010 . . . .

Prohlaˇsuji, ˇze jsem tuto diplomovou pr´aci vypracoval samostatnˇe. Uvedl jsem vˇsechny liter´arn´ı prameny a publikace, ze kter ´ych jsem ˇcerpal.

(4)
(5)
(6)
(7)

velikost operaˇcn´ı pamˇeti poˇc´ıtaˇce. Sezn´amit se zn´am ´ymi algoritmy, jejich nedostatky a n´asledn ´ymi optimalizacemi, d´ale navrhnout komponentu pro tˇr´ıdˇen´ı dat s pouˇzit´ım tˇechto algoritm ˚u. Tuto komponentu implementovat v jazyce C++ nad jiˇz implementova-nou strukturou perzistentn´ıho pole a n´aslednˇe ji otestovat, popˇr. d´ale optimalizovat.

Kl´ıˇcov ´a slova: Tˇr´ıdˇen´ı dat, extern´ı tˇr´ıdˇen´ı, tˇr´ıd´ıc´ı algoritmus, sloˇzitost algoritmu, C++

Abstract

The aim of this thesis is to describe the problem of data sorting whose size is larger than the main memory. Familiarize with known algorithms, their shortcomings and subse-quent optimization, design component for sorting the data using these algorithms. This component implemented in C++ over the structure of the implemented persistent array and consequently they are tested, respectively. further optimize.

(8)
(9)

Obsah

1 Uvod´ 11

1.1 C´ıl diplomov´e pr´ace . . . 11

2 Uvod do tˇr´ıd´ıc´ıch algoritm ˚u´ 13 2.1 Algoritmus . . . 13

2.2 Tˇr´ıd´ıc´ı algoritmy . . . 13

2.3 Z´akladn´ı typy tˇr´ıd´ıc´ıch algoritm ˚u . . . 14

3 Algoritmy pro tˇr´ıdˇen´ı na extern´ım ´uloˇziˇsti 15 3.1 Uvaˇzovan ´y model . . . 15

3.2 Popis extern´ıho mergesortu . . . 15

3.3 Spojovac´ı algoritmy . . . 19

4 Komponenta perzistentn´ıho pole 23 4.1 Popis komponenty . . . 23

4.2 Pˇr´ıklad pr´ace s perzistentn´ım polem . . . 23

5 Anal ´yza a n´avrh komponenty pro extern´ı tˇr´ıdˇen´ı prvk ˚u 29 5.1 Specifikace poˇzadavk ˚u . . . 29

5.2 Specifikace pomoc´ı pˇr´ıpadu uˇzit´ı . . . 29

5.3 Tˇr´ıdn´ı diagram . . . 30

6 Implementace 33 6.1 Tˇr´ıda ArrayTest . . . 33

6.2 ˇSablona RunInfo . . . 34

6.3 ˇSablona SortArray . . . 34

6.4 Pouˇzit´e technologie a programov´e vybaven´ı . . . 39

7 Testy 41 7.1 Data pouˇzit´a pro testov´an´ı . . . 41

7.2 Grafy . . . 43 7.3 Shrnut´ı testov´an´ı . . . 45 8 Z´avˇer 49 9 Reference 51 Pˇr´ılohy 51 A Uˇzivatelsk´a pˇr´ıruˇcka 53 B Obsah pˇriloˇzen´eho CD 55

(10)
(11)

Seznam tabulek

1 Seznam vstupn´ıch soubor ˚u k testov´an´ı a jejich parametry . . . 42 2 Mˇeˇren´ı ˇcasu tˇr´ıdˇen´ı vstupn´ıch soubor ˚u pro r ˚uzn´e velikosti hlavn´ı pamˇeti . 42

(12)
(13)

Seznam obr ´azk ˚

u

1 Prvn´ı f´aze extern´ıho mergesortu . . . 16

2 Druh´a f´aze extern´ıho mergesortu vyuˇz´ıvaj´ıc´ı dva pr ˚uchody . . . 16

3 Diagram pˇr´ıpadu uˇzit´ı syst´emu . . . 30

4 Tˇr´ıdn´ı diagram komponenty pro tˇr´ıdˇen´ı prvk ˚u . . . 32

5 Graf tˇr´ıdˇen´ı souboru test setrideny.txt . . . 43

6 Graf tˇr´ıdˇen´ı souboru test1.txt . . . 44

7 Graf tˇr´ıdˇen´ı souboru test2.txt . . . 44

8 Graf tˇr´ıdˇen´ı souboru test3.txt . . . 45

9 Graf tˇr´ıdˇen´ı souboru test4.txt . . . 46

(14)
(15)

Seznam algoritm ˇ

u

1 Uk´azka pseudok ´odu extern´ıho mergesortu . . . 17

2 Uk´azka pseudok ´odu algoritmu posloupnosti spotˇreby . . . 21

3 Uk´azka pseudok ´odu algoritmu seskupov´an´ı blok ˚u . . . 22

4 Pseudok ´od algoritmu naˇcti-setˇr´ıd’-uloˇz . . . 36

5 Pseudok ´od k-cestn´eho sl´ev´an´ı bez rekurze . . . 37

6 Pseudok ´od metody Sl´evej() potˇrebn´e k algoritmu k-cestn´eho sl´ev´an´ı bez rekurze . . . 38

(16)
(17)

Seznam v ´ypis ˚

u zdrojov ´eho k ´

odu

1 Uk´azka v ´ypisu vektor ˚u ze souboru perzistentn´ıho pole . . . 24

2 V ´ystup z metody v ´ypisu vektor ˚u ze souboru perzistentn´ıho pole . . . 25

3 Uk´azka z´apisu vektor ˚u do souboru perzistentn´ıho pole . . . 26

(18)
(19)

1

Uvod

´

V dneˇsn´ı uspˇechan´e dobˇe si ˇclovˇek snaˇz´ı vˇsemoˇzn ´ymi zp ˚usoby ulehˇcit svou pr´aci. S ob-rovsk ´ym boomem poˇc´ıtaˇcov´e techniky v devades´at ´ych letech minul´eho stolet´ı postupnˇe nar ˚ustalo nasazov´an´ı poˇc´ıtaˇc ˚u i do dˇr´ıve tˇeˇzko pˇredstaviteln ´ych pozic. S poˇc´ıtaˇcem um´ı pracovat dˇeti, poˇc´ıtaˇce dnes dokonce ˇr´ıd´ı letouny. K denn´ı rutinˇe patˇr´ı komunikovat pˇres email, m´ıt pˇr´ıstup k bankovn´ımu kontu prostˇrednictv´ım internetu, v´est videokonference, pˇren´aˇset multim´edia. Um´ıte si bez poˇc´ıtaˇce pˇredstavit ˇzivot? Poˇcitaˇce zkr´atka pronikly do ˇzivot ˚u nˇekolika miliard lid´ı na t´eto planetˇe.

Z hlediska informatiky je to jistˇe pozitivn´ı informace. A nyn´ı si zkuste pˇredstavit, kolik dat vytvoˇr´ı dennˇe, t ´ydnˇe, mˇes´ıˇcnˇe kaˇzd ´y uˇzivatel pracuj´ıc´ı s poˇcitaˇcem. Kaˇzd ´ym n´akupem v internetov´em obchodˇe, kaˇzd ´ym odeslan ´y emailem. Pokud tyto data chceme d´ale vyuˇz´ıvat, je potˇreba je dˇr´ıve nebo pozdˇeji setˇr´ıd´ıt. Pokud se mnoˇzina dat k setˇr´ıdˇen´ı nevejde do hlavn´ı pamˇeti poˇc´ıtaˇce, kter ´y m´a dan´a data setˇr´ıdit, je nutno pouˇzit extern´ı tˇr´ıdˇen´ı. To zajist´ı spr´avn´e setˇr´ıdˇen´ı dat ˇr´adovˇe vˇetˇs´ıch neˇz samotn´a n´am dostupn´a ˇc´ast hlavn´ı pamˇeti.

1.1 C´ıl diplomov ´e pr ´ace

C´ılem m´e diplomov´e pr´ace je popsat souˇcasn ´y stav zn´am ´ych algoritm ˚u pro tˇr´ıdˇen´ı dat na extern´ım ´uloˇziˇsti a jejich optimalizace. D´ale se sezn´amit s jiˇz implementovan ´ymi tˇr´ıdami perzistentn´ıho pole, popsat jejich strukturu, chov´an´ı a pˇredv´est na nich nˇekolik z´akladn´ıch operac´ı.

Pro tyto tˇr´ıdy navrhnout obecnou komponentu pro tˇr´ıdˇen´ı vyuˇz´ıvaj´ıc´ı pro tento pˇr´ıpad co nejvhodnˇejˇs´ı tˇr´ıd´ıc´ı algoritmus. D´ale navrhnout a popsat vhodnou optimalizaci, kter´a bude posl´eze tak´e implementov´ana. Pot´e popsat v ´yslednou implementaci a v z´avˇeru prov´est nˇekolik srovn´avac´ıch test ˚u a uk´azku pr´ace s v ´yslednou aplikac´ı.

(20)
(21)

2

Uvod do tˇr´ıd´ıc´ıch algoritm ˚

´

u

2.1 Algoritmus

Algoritmus je pˇredpis, kter ´y se skl´ad´a z koneˇcn´eho poˇctu krok ˚u a kter ´y zajist´ı, ˇze na z´akladˇe vstupn´ıch dat budou poskytnuta data v ´ystupn´ı. Kaˇzd ´y algoritmus m´a n´asleduj´ıc´ı vlastnosti:

• Koneˇcnost - poˇzadovan ´y v ´ysledek mus´ı b ´yt poskytnut v rozumn´em ˇcase. Za ro-zumn ´y lze povaˇzovat ˇcas, po kter´em bude v ´ysledek v ´ypoˇctu relevantn´ı vzhledem ke vstupn´ım dat ˚um.

• Hromadnost – Vstupn´ı data nejsou v popisu algoritmu reprezentov´ana konkr´etn´ımi hodnotami, ale sp´ıˇse mnoˇzinami, ze kter ´ych lze data vybrat.

• Jednoznaˇcnost – Kaˇzd ´y pˇredpis je sloˇzen z krok ˚u, kter´e na sebe navazuj´ı. Kaˇzd ´y krok m ˚uˇzeme charakterizovat jako pˇrechod z jednoho stavu algoritmu do jin´eho, pˇriˇcemˇz kaˇzd ´y stav je urˇcen zpracov´avan ´ymi daty. Vˇzdy mus´ı b ´yt urˇceno, kter ´y krok n´asleduje.

• Opakovatelnost – Pˇri pouˇzit´ı stejn ´ych vstupn´ıch dat mus´ıme dostat stejn´a data v ´ystupn´ı.

• Resultativnost – Algoritmus vede ke spr´avn´emu v ´ysledku [2]. 2.2 Tˇr´ıd´ıc´ı algoritmy

Tˇr´ıd´ıc´ı algoritmus je ´uloha, jej´ımˇz c´ılem je zajistit seˇrazen´ı dan´eho souboru dat podle pˇredem urˇcen´eho kl´ıˇce (numericky, abecednˇe, atd.) v co nejkratˇs´ım ˇcase. Probl´em tˇr´ıdˇen´ı patˇr´ı mezi nejv´ıce studovan´e probl´emy v poˇc´ıtaˇcov´e vˇedˇe, s nar ˚ustaj´ıc´ım trendem za-znamen´av´an´ı a shromaˇzd’ov´an´ı digit´aln´ıch ´udaj ˚u rostou i poˇzadavky na tˇr´ıdˇen´ı velk´eho mnoˇzstv´ı dat [1].

2.2.1 D ˇelen´ı tˇr´ıd´ıc´ıch algoritm ˚u

Pokud se vˇsechna data k seˇrazen´ı nevejdou do hlavn´ı pamˇeti poˇc´ıtaˇce, prob´ıh´a extern´ı tˇr´ıdˇen´ı, kdy je k mezioperac´ım pouˇzito ˇr´adovˇe pomalejˇs´ı pamˇeti, dnes pˇrev´aˇznˇe pevn´e disky. Tyto algoritmy narozd´ıl od klasick ´ych tˇr´ıd´ıc´ıch algoritm ˚u mus´ı br´at v ´uvahu mno-hem vˇetˇs´ı n´aklady pˇri ˇcten´ı nebo z´apisu na extern´ı m´edium. Algoritmy pro tˇr´ıdˇen´ı se tedy podle pamˇeti, ve kter´e prob´ıhaj´ı, dˇel´ı na:

• Vnitˇrn´ı – cel ´y soubor dat k setˇr´ıdˇen´ı se vejde do hlavn´ı pamˇeti poˇc´ıtaˇce, k poloˇzk´am lze pˇristupovat n´ahodnˇe se zanedbateln ´ymi n´aklady.

• Vnˇejˇs´ı – do hlavn´ı pamˇeti poˇc´ıtaˇce se vejde jen ˇc´ast dat k setˇr´ıdˇen´ı, algoritmy pro vnˇejˇs´ı tˇr´ıdˇen´ı minimalizuj´ı poˇcet pˇr´ıstup ˚u na disk, pˇr´ıpadnˇe ˇreˇs´ı dalˇs´ı optimalizace pro co moˇzno nejlepˇs´ı pˇrekr ´yv´an´ı procesorov´eho a vstupnˇe/v ´ystupn´ıho ˇcasu [1].

(22)

14

Podle dalˇs´ıch vlastnost´ı pak na:

• Pˇrirozen´e - pˇrirozen ´y algoritmus pracuje rychleji na jiˇz ˇc´asteˇcnˇe setˇr´ıdˇen´e mnoˇzinˇe dat.

• Stabiln´ı - stabiln´ı tˇr´ıd´ıc´ı algoritmy zachov´avaj´ı relativn´ı poˇrad´ı z´aznam ˚u se stejnou hodnotou kl´ıˇce. Pokud tedy v souboru dat existuj´ı dva z´aznamy se stejnou hodno-tou kl´ıˇce, mus´ı algoritmus zachovat jejich vz´ajemn´e poˇrad´ı.

2.2.2 Sloˇzitost tˇr´ıd´ıc´ıch algoritm ˚u

• ˇCasov´a - ˇcasovou sloˇzitost´ı rozum´ıme funkci, kter´a kaˇzd´e mnoˇzinˇe vstupn´ıch dat pˇriˇrazuje poˇcet operac´ı vykonan ´ych pˇri v ´ypoˇctu podle dan´eho algoritmu.

• Pamˇet’ov´a - pamˇet’ovou sloˇzitost definujeme jako z´avislost pamˇet’ov ´ych n´arok ˚u al-goritmu na vstupn´ıch datech.

ˇ

Casov´a sloˇzitost v ´ypoˇcetn´ıch metod zpravidla vzbuzuje menˇs´ı respekt neˇz sloˇzitost pamˇet’ov´a [2].

2.3 Z ´akladn´ı typy tˇr´ıd´ıc´ıch algoritm ˚u

• Bubblesort - Pˇri neust´al´em proch´azen´ı seznamu porovn´av´ame dva sousedn´ı prvky, pokud nejsou ve spr´avn´em poˇrad´ı, vymˇen´ıme je. Proch´azen´ı seznamu skonˇc´ı, po-kud je cel ´y setˇr´ıdˇen. Jednoduch ´y na implementaci. Pˇrirozen ´y, stabiln´ı. Vyˇzaduje velk´e mnoˇzstv´ı z´apis ˚u do pamˇeti. Pr ˚umˇern´a i maxim´aln´ı sloˇzitost: O(n2).

• Quicksort - Patˇr´ı mezi algoritmy typu rozdˇel a panuj. Nejprve na seznamu zvol´ıme pivota (nejl´epe medi´an cel´eho seznamu). Algoritmus pak seznam rozdˇel´ı na dva znamy, v nˇemˇz v jednom jsou prvky menˇs´ı neˇz pivot, ve druh´em vˇetˇs´ı. Oba tyto se-znamy se stejn ´ym postupem rekurzivnˇe setˇr´ıd´ı. Sloˇzitost algoritmu z´avis´ı na volbˇe pivota, poˇc´ıtat medi´an u velk´eho mnoˇzstv´ı dat vˇsak nen´ı efektivn´ı, pouˇz´ıv´a se tedy n´ahodnˇe vybran ´y prvek (nepˇr´ıliˇs efektivn´ı), nebo medi´an n´ahodnˇe vybran´e mal´e ˇc´asti seznamu. Nepˇrirozen ´y, nestabiln´ı. Pr ˚umˇern´a sloˇzitost O(n · log n), maxim´aln´ı sloˇzitost: O(n2)(pˇri pouˇzit´ı vˇzdy nejhorˇs´ıho moˇzn´eho pivota).

• Mergesort - ˇRazen´ı sl´ev´an´ım, dalˇs´ı z algoritm ˚u typu rozdˇel a panuj. Algoritmus postupnˇe dˇel´ı seznam na menˇs´ı ˇc´asti, dokud nen´ı rozdˇelen ´y na jednotliv´e prvky (trivi´aln´ı probl´em). Pak jej postupnˇe spojuje zp´atky s pˇrihl´ednut´ım na hodnoty kl´ıˇc ˚u (v ´ybˇer nejvhodnˇejˇs´ıho kl´ıˇce). Pˇrirozen ´y, stabiln´ı.

Pr ˚umˇern´a i maxim´aln´ı sloˇzitost: O(n · log n).1

(23)

3

Algoritmy pro tˇr´ıd ˇen´ı na extern´ım ´

uloˇzi ˇsti

Jak jsme jiˇz uvedli dˇr´ıve, tˇr´ıdˇen´ı mimo hlavn´ı pamˇet sebou pˇrin´aˇs´ı nov´e n´aroky na efek-tivitu algoritmu, jde pˇredevˇs´ım o probl´emy spojen´e s ukl´ad´an´ım na ˇr´adovˇe pomalejˇs´ı m´edium, pevn ´y disk. Ten dnes pˇredstavuje nejpomalejˇs´ı ˇc´ast poˇc´ıtaˇce, jeho typick´e vlast-nosti vych´az´ı ze star´e kontrukce vyuˇz´ıvaj´ıc´ı magnetickou indukci a mechanick´e pˇresouv´an´ı z´aznamov ´ych hlav. Naˇstˇest´ı jsou dostupn´e plnˇe elektronick´e SSD disky, u kter ´ych odpa-daj´ı mechanick´e neduhy pˇri z´apisu ˇci ˇctˇen´ı dat. Vyhneme se tak dosti velk´e pˇr´ıstupov´e dobˇe a z´avislosti na fyzick´em um´ıstˇen´ı zapsan ´ych dat, nemluvˇe o pˇr´ıpadn´e fragmentaci soubor ˚u [4].

3.1 Uvaˇzovan ´y model

V cel´e diplomov´e pr´aci i pozdˇejˇs´ım ˇreˇsen´ı uvaˇzuji n´asleduj´ıc´ı model: Pˇredpokl´ad´am, ˇze poˇc´ıtaˇc, na kter´em bude tˇr´ıdˇen´ı prob´ıhat, m´a jednu hlavn´ı pamˇet’, jeden procesor a je-den disk, kter´e budu pouˇz´ıvat pro operace potˇrebn´e k bˇehu algoritmu. Jako jednu stranu pamˇeti uvaˇzuji takovou ˇc´ast hlavn´ı pamˇeti, kter´a m´a stejnou velikost, jako alokaˇcn´ı jed-notka pouˇz´ıvan´eho souborov´eho syst´emu.

Pˇrev´aˇzn´a vˇetˇsina algoritm ˚u pro vnitˇrn´ı tˇr´ıdˇen´ı nem ˚uˇze b ´yt upravena tak, aby efek-tivnˇe pracovala jako algoritmus pro vnˇejˇs´ı tˇr´ıdˇen´ı. Metody vyuˇz´ıvaj´ıc´ı sekvenˇcn´ıho pˇr´ıstupu jako je napˇr. insertsort a selectsort m ˚uˇzeme z dalˇs´ıch ´uvah rovnou vylouˇcit. V milu-losti byly algoritmy pro vnitˇrn´ı tˇr´ıdˇen´ı studov´any tak´e v souvislost´ı s virtu´aln´ı pamˇet´ı, v ´ysledky vˇsak nebyly tak slibn´e d ˚usledkem nadmˇern´eho poˇctu odkl´adac´ıch str´anek. Snaha pˇrepracovat heapsort a quicksort pro vnˇejˇs´ı tˇr´ıdˇen´ı nebyla efektivn´ı, nepodaˇrilo se dos´ahnout tak mal´eho poˇctu vstupnˇe v ´ystupn´ıch operac´ı jako u mergesortu, kter ´y je z tohoho hlediska nejlepˇs´ım algoritmem pro vnˇejˇs´ı tˇr´ıdˇen´ı.

V posledn´ıch letech se v ´yzkum zamˇeˇruje na jeho optimalizaci vedouc´ı k co nejvˇetˇs´ımu zefektivnˇen´ı a optim´aln´ımu pˇrekr ´yv´an´ı procesorov´eho a vstupnˇe/v ´ystupn´ıho ˇcasu [1]. 3.2 Popis extern´ıho mergesortu

Pˇredpokl´adejme, ˇze soubor, kter ´y m´a b ´yt setˇr´ıdˇen, m´a N stran a ˇze m´ame k dispozici B stran v hlavn´ı pamˇeti. Tˇr´ıd´ıc´ı algoritmus pak prob´ıh´a ve dvou f´az´ıch:

• V prvn´ı f´azi je soubor rozdˇelen do ˇc´ast´ı, kter´e se naz ´yvaj´ı skupiny nebo vl´akna. Cel´a skupina m ˚uˇze b ´yt zcela uloˇzena v B stran´ach hlavn´ı pamˇeti a tud´ıˇz existuje N/B skupin vyprodukovan ´ych v t´eto f´azi. Kaˇzd´a skupina je setˇr´ıdˇena nez´avisle v hlavn´ı pamˇeti nˇekter ´ym z vnitˇrn´ıch tˇr´ıd´ıc´ıch algoritm ˚u a pak zaps´ana zpˇet na disk, viz Obr´azek 1.

• V pr ˚ubˇehu druh´e f´aze jsou skupiny sl´ev´any tak, aby vyrobily menˇs´ı poˇcet sku-pin a nakonec byly spojeny do jedin´e v ´ysledn´e. Spojovac´ı f´aze se m ˚uˇze skl´adat z nˇekolika pr ˚uchod ˚u. Dostupnou pamˇet’ ve druh´e f´azi rozdˇel´ıme tak, aby vznikla jedna vyrovn´avac´ı pamˇet’ pro v ´ystupn´ı soubor a zbytek pamˇeti se rozdˇelil jako ˇctec´ı vyrovn´avac´ı pamˇet jednotliv ´ych skupin. V kaˇzd´em pr ˚uchodu se z kaˇzd´e skupiny,

(24)

16

Obr´azek 1: Prvn´ı f´aze extern´ıho mergesortu

Obr´azek 2: Druh´a f´aze extern´ıho mergesortu vyuˇz´ıvaj´ıc´ı dva pr ˚uchody

resp. jej´ıho ˇctec´ıho z´asobn´ıku, vybere nejmenˇs´ı popˇr. nejvˇetˇs´ı prvek a ten se po-rovn´av´a s dalˇs´ımi takto z´ıskan ´ymi prvky z ostatn´ıch skupin. Na konci kaˇzd´eho pr ˚uchodu dostaneme vˇzdy jeden prvek, kter ´y zap´ıˇseme na v ´ystupn´ı z´asobn´ık. Po-kud je v ´ystupn´ı z´asobn´ık pln ´y, zap´ıˇse se do v ´ysledn´eho souboru, obdobnˇe, poPo-kud je nˇekter ´y ze vstupn´ıch z´asobn´ık ˚u pr´azdn ´y, naˇcte se do nˇej dalˇs´ı ˇc´ast pˇr´ısluˇsn´e sku-piny [3], viz Obr´azek 2.

V ´ykonnost extern´ıho mergesortu z´aleˇz´ı mj. na v ´ybˇeru spojovac´ıho sch´ema, jak ´ym se vyb´ıraj´ı skupiny pro spojov´an´ı ve druh´e ˇc´asti algoritmu. R ˚uzn´e postupy totiˇz mohou v´est ke znaˇcn ´ym v ´ykonov ´ym rozd´ıl ˚um [1].

3.2.1 Algoritmy pro tvorbu skupin

Pro tvorbu skupin se bˇeˇznˇe pouˇz´ıvaj´ı dva algoritmy:

Prvn´ı, naz ´yvaj´ıc´ı se naˇcti-setˇrid’-uloˇz, napln´ı vˇsechny dostupn´e str´anky hlavn´ı pamˇeti z´aznamy ze souboru k seˇrazen´ı a spust´ı vnitˇrn´ı tˇr´ıdic´ı algoritmus heapsort nebo quicksort. V ´ysledek je zaps´an zpˇet na disk jako setˇr´ıdˇen´a skupina. Tento postup se opakuje, dokud nejsou setˇr´ıdˇeny vˇsechny z´aznamy. Jednotliv´e skupiny tedy maj´ı velikost shodnou s ve-likost´ı dostupn´e hlavn´ı pamˇeti.

Druh ´y algoritmus se naz ´yv´a v´ymˇenn´y v´ybˇer. Vyuˇz´ıv´a minim´aln´ı haldu k v ´ybˇeru kl´ıˇce s minim´aln´ı hodnotou. Halda se nejprve napln´ı, pak je z´aznam s nejmenˇs´ı hodnotou kl´ıˇce (vrchol haldy) pˇresunut z haldy do v ´ystupn´ıho z´asobn´ıku a t´ım uvoln´ı m´ısto pro nov ´y prvek. Dalˇs´ı prvek, kter ´y m´a b ´yt pˇresunut do v ´ystupn´ıho z´asobn´ıku, mus´ı m´ıt vˇetˇs´ı

(25)

Algoritmus 1: Uk´azka pseudok ´odu extern´ıho mergesortu Input: file BLOCKSIZE; RAMSIZE; N=size(file)/BLOCKSIZE; B=RAMSIZE/BLOCKSIZE; //prvn´ı ˇc´ast

while file != empty do for i:=1 to N/B do ram:=load(file)/RAMSIZE; sort(ram); write(filesort, i); // druh´a ˇc´ast for b:=1 to B-1 do alokuj(Bi, B/ N+1); alokuj(Bout, B/ N+1); for b:=1 to N/B do Bb:=read(filesort, b, B/ N+1);

while filesort != empty do

Bout= merge(B1... BN/B);

if Bxis empty then

dopl ˇn(filesort, x + pˇreˇcteno);

if Boutis full then

write(Bout, finallyfile);

(26)

18

kl´ıˇcovou hodnotu, neˇz posledn´ı vyjmut ´y prvek. Pokud se v souboru vyskytnou z´aznamy s menˇs´ı kl´ıˇcovou hodnotou, neˇz posledn´ı prvek vloˇzen ´y do v ´ystupn´ıho z´asobn´ıku, um´ıst´ı se do nov´e minim´aln´ı haldy. T´ım se postupnˇe prvn´ı halda zmenˇsuje a druh´a zvˇetˇsuje. Pˇri vypr´azdnˇen´ı prvn´ı haldy je dokonˇcena tvorba prvn´ı skupiny a prvky z dalˇs´ı haldy jiˇz pln´ı dalˇs´ı skupinu. Tento proces konˇc´ı, kdyˇz v souboru nezb ´yvaj´ı ˇz´adn´e dalˇs´ı z´aznamy k setˇr´ıdˇen´ı [3].

Jak bylo prok´az´ano [3], pr ˚umˇern ´y poˇcet skupin vytvoˇren ´ych v ´ymˇenn ´ym v ´ybˇerem je poloviˇcn´ı oproti velikosti skupin, vytvoˇren ´ych algoritmem naˇcti-setˇrid’-uloˇz. To m´a vliv na v ´ypoˇcetn´ı ˇcas druh´e ˇc´asti algoritmu, menˇs´ı poˇcet skupin totiˇz zkr´at´ı ˇcas potˇrebn ´y k vy-kon´an´ı druh´e ˇc´asti extern´ıho mergesortu. Algoritmus v ´ymˇenn ´y v ´ybˇer m´a st´alejˇs´ı pr ˚ubˇeh vstupnˇe/v ´ystupn´ıch operac´ı a dosahuje lepˇs´ıch v ´ysledk ˚u na jiˇz ˇc´asteˇcnˇe pˇredtˇr´ıdˇen ´ych datech. Mezi jeho nev ´yhody patˇr´ı nutnost souˇcasn´eho ˇcten´ı z´aznam ˚u ze vstupn´ıho z´asob-n´ıku a z´apis na v ´ystupn´ı z´asobn´ık. Jsou-li oba soubory uloˇzeny na stejn´em disku, je potˇreba v´ıce ˇcasu na reˇzii pˇri ˇcten´ı a z´apisu dat, vypl ´yvaj´ıc´ı z tˇechto poˇzadavk ˚u. Pokud ovˇsem m´ame k dispozici dva disky, je v ´ymˇenn ´y v ´ybˇer lepˇs´ı volbou [1].

3.2.2 Spr ´ava pam ˇeti pro z ´aznamy r ˚uzn ´ych d ´elek

V re´aln´em svˇetˇe potˇrebujeme pracovat se z´aznamy r ˚uzn ´ych d´elek. V ´yˇse popsan´e algo-ritmy vˇsak nejsou pˇr´ımo pouˇziteln´e pro z´aznamy s r ˚uzn ´ymi d´elkami, protoˇze pamˇet’ov ´y prostor pro tˇr´ıdˇen´ı je pevnˇe d´an a poˇcet z´aznam ˚u, kter´e mohou b ´yt vyjmuty z tohoto prostoru, nen´ı pˇredem zn´am. Budeme pˇredpokl´adat, ˇze se pamˇet’ov ´y prostor skl´ad´a z nˇekolika rozsah ˚u, protoˇze nen´ı moˇzn´e alokovat libovolnˇe velk´e ˇc´asti soused´ıc´ı pamˇeti. Postup je n´asleduj´ıc´ı: Pˇri spuˇstˇen´ı algoritmu pro tvorbu skupin jsou z´aznamy s promˇennou d´elkou ˇcteny ze vstupu a vkl´ad´any do pamˇet’ov´eho prostoru. Tato metoda m´a naj´ıt m´ısto pro kaˇzd ´y nov ´y z´aznam uvnitˇr existuj´ıc´ıho pamˇet’ov´eho prostoru. Pokud nen´ı nalezeno ˇz´adn´e voln´e m´ısto, je z´aznam pˇresunut z pamˇet’ov´eho prostoru na v ´ystup a t´ım vytvoˇr´ı prostor pro nov ´y vstup. Pokud z´aznamy neobsad´ı vˇsechna vytvoˇren´a voln´a m´ısta, mus´ı pak syst´em sledovat voln´e segmenty a kontrolovat moˇznost slouˇcen´ı potencion´aln´ıch sousedn´ıch voln ´ych segment ˚u. V n´asleduj´ıc´ıch dvou heuristick ´ych metod´ach je pops´ano hled´an´ı voln ´ych segment ˚u.

Dalˇs´ı vyhovuj´ıc´ı - tato metoda sekvenˇcnˇe vyhled´av´a vˇsechny voln´e segmenty pamˇeti, zaˇc´ın´a od pozice, kde doˇslo k posledn´ımu vloˇzen´ı, a prob´ıh´a, dokud nenalezne dostateˇcnˇe velkou ˇc´ast pamˇeti pro uloˇzen´ı nov´eho z´aznamu. Jelikoˇz m ˚uˇze b ´yt vyhled´av´an´ı dosti n´aroˇcn´e, zav´ad´ı se prahov´a hodnota k omezen´ı poˇctu zkouman ´ych voln ´ych segment ˚u. Pokud je tento limit dosaˇzen a nebyl nalezen ˇz´adn ´y voln ´y segment, snaˇz´ı se algorit-mus pˇresunout z´aznam soused´ıc´ı s voln ´ym segmentem z jeho aktu´aln´ı pozice k dalˇs´ımu voln´emu segmentu, kter ´y byl zkoum´an v pr ˚ubˇehu stejn´eho vyhled´av´an´ı. Pokud tento pˇresun vytvoˇr´ı poˇzadovan´e m´ısto, je z´aznam vloˇzen do pamˇet’ov´eho prostoru, pokud nevytvoˇr´ı, je jeden nebo v´ıce existuj´ıc´ıch z´aznam ˚u odstranˇeno z pamˇet’ov´eho prostoru a vytvoˇr´ı tak vhodn´e voln´e m´ısto.

Nejlepˇs´ı vyhovuj´ıc´ı - v t´eto metodˇe jsou nov´e z´aznamy vkl´ad´any do nejmenˇs´ıho voln´eho segmentu, kter ´y je natolik velk ´y, aby dan ´y z´aznam pˇrijal. Pro efektivn´ı vyhled´av´an´ı vhodn´eho voln´eho segmentu sleduje algoritmus velikosti voln ´ych segment ˚u v bin´arn´ım

(27)

stromu. Pˇri vkl´ad´an´ı nov´eho z´aznamu prohled´a algoritmus bin´arn´ı strom, aby nalezl voln ´y segment minim´aln´ı velikosti, kter ´y je vˇetˇs´ı nebo roven velikosti nov´eho z´aznamu. V pˇr´ıpadˇe, ˇze neexistuje ˇz´adn ´y voln ´y segment, jsou existuj´ıc´ı z´aznamy odstranˇeny, do-kud nen´ı dostatek voln´eho m´ısta.

Podle test ˚u, kter´e byly provedeny, dosahuje metoda nejlepˇs´ı vyhovuj´ıc´ı aˇz 95% vyuˇzit´ı pamˇeti pro velk´e pamˇet’ov´e rozsahy. Pro menˇs´ı pamˇet’ov´e rozsahy je vyuˇzit´ı kolem 75%. Metoda nejlepˇs´ı vyhovuj´ıc´ı je d´ale ˇcasovˇe ´uspornˇejˇs´ı - n´aklady na vyhled´av´an´ı v t´eto metodˇe totiˇz nar ˚ustaj´ı s poˇctem voln ´ych segment ˚u logaritmicky (d´ıky vyuˇzit´ı bin´arn´ıho stromu). Pro z´aznamy s promˇennou velikost´ı je tedy metoda nejlepˇs´ı vyhovuj´ıc´ı s meto-dou v ´ymˇenn´eho v ´ybˇeru tou nejlepˇs´ı kombinac´ı [1].

3.3 Spojovac´ı algoritmy

Vzhledem k tomu, ˇze je spojov´an´ı skupin pˇrev´aˇznˇe vstupnˇe/v ´ystupn´ı operac´ı, snaˇz´ı se vˇsechny algoritmy minimalizovat poˇcet pˇr´ıstup ˚u na disk. Vyv´aˇzen ´y k-cestn´y mergesort tˇr´ıd´ı data pouˇzit´ım opakovan´eho sluˇcov´an´ı. Rozdˇel´ı vstup do dvou skupin opakovan ´ym ˇcten´ım blok ˚u dat ze vstupu, kter´e zapln´ı hlavn´ı pamˇet’, skupina se setˇr´ıd´ı, a pak se zap´ıˇse do dalˇs´ı skupiny. Ve druh´e f´azi se opakovanˇe spojuj´ı dvˇe skupiny do jedn´e ze dvou v ´ystupn´ıch skupin, dokud nevznikne jedna setˇr´ıdˇen´a skupina [7].

Dˇr´ıvˇejˇs´ı studie uk´azaly, u v´ıcecestn´eho spojov´an´ı, obecnˇe k-cestn´eho spojov´an´ı, zvo-len´ım k co nejvyˇsˇs´ıho nemus´ı vˇzdy v´est ke zlepˇsen´ı v ´ykonnosti. Jedno z ˇreˇsen´ı je vloˇzit nejprve tolik pr´azdn ´ych skupin, kolik je potˇreba k vytvoˇren´ı vˇsech skupin-1, dˇeliteln ´ych k-1. Pak algoritmus spoj´ı v kaˇzd´em pr ˚uchodu k nejkratˇs´ıch skupin, dokud nez ˚ustane jen jedna. Tento postup vˇsak nedosahuje pˇrekr ´yv´an´ı mezi vstupnˇe/v ´ystupn´ım a CPU ˇcasem: procesor z ˚ustane v neˇcinnosti, zat´ımco je k z´asobn´ık ˚u plnˇeno ˇc´astmi odpov´ıdaj´ıc´ıch sku-pin naˇc´ıtan ´ych z disku. Tento probl´em ˇreˇs´ı prognostick´a metoda, metoda dvojit´eho vy-rovn´av´an´ı nebo metoda prokl´adan´eho rozvrˇzen´ı.

Prognostick´a metoda - tato metoda sleduje ˇctec´ı z´asobn´ık, kter ´y bude vypr´azdnˇen jako prvn´ı a pouˇz´ıv´a dalˇs´ı zvl´aˇstn´ı z´asobn´ık ke ˇcten´ı dalˇs´ı vhodn´e ˇc´asti z disku, dokud obsah zb ´yvaj´ıc´ıch z´asobn´ık ˚u nepokraˇcuje ke zpracov´an´ı. Vylepˇsen´a prognostick´a metoda zav´ad´ı posloupnost spotˇreby k urˇcen´ı, kter ´y ze z´asobn´ık ˚u bude vypr´azdnˇen jako prvn´ı a ˇcten´ı dat z disku zaˇc´ın´a jiˇz ve chv´ıli, kdy je v pamˇeti voln ´ych m stran. Nemus´ıme tedy ˇcekat na uvolnˇen´ı cel´eho z´asobn´ıku nˇekter´e skupiny [1].

Dvojit´e vyrovn´av´an´ı - v t´eto metodˇe se pro kaˇzdou skupinu vytvoˇr´ı dva z´asobn´ıky, je-den pro prov´adˇen´ı V/V operac´ı a druh ´y pro zpracov´an´ı. M ˚uˇze b ´yt pouˇzita bud’ pˇri ˇcten´ı z disku nebo pˇri z´apisu na nˇej. Oproti prognostick´e metodˇe vyˇzaduje tato metoda v´ıce pamˇeti, nebo sn´ıˇzen´ı velikosti st´avaj´ıc´ıho z´asobn´ıku. D´ıky dvˇema z´asobn´ık ˚um m ˚uˇze b ´yt dosaˇzeno pˇrekr ´yv´an´ı mezi V/V a CPU ˇcasem, ale nutno poznamenat, ˇze nem´a vyuˇzit´ı u t´emˇeˇr setˇr´ıdˇen ´ych dat [5]. V rozˇs´ıˇren´ı t´eto metody, naz ´yvaj´ıc´ım se rovnomˇern´e vyrovn´av´an´ı, se pro kaˇzdou skupinu vytvoˇr´ı m z´asobn´ık ˚u. Nyn´ı nast´av´a ot´azka, jak brzy zah´ajit nov´e ˇcten´ı pro zaplnˇen´ı pr´azdn ´ych z´asobn´ık ˚u. Pokud zaˇcneme ˇc´ıst, kdyˇz je pr´azdn ´ych m-1 z´asobn´ık ˚u, minimalizujeme vyhled´avac´ı ˇcas, nebot’ vˇsech m-1 blok ˚u bude ˇcteno z po sobˇe jdouc´ıch m´ıst. T´ım vˇsak nen´ı zaruˇceno ´upln´e pˇrekryt´ı CPU a V/V ˇcasu, protoˇze pˇri ˇcten´ı m-1 blok ˚u m ˚uˇze CPU z ˚ustat neˇcinn ´y. V tomto okamˇziku se vyuˇz´ıv´a vlastnosti

(28)

20

modern´ıch diskov ´ych syst´em ˚u, kter´e rozdˇel´ı ˇcten´ı velk´eho mnoˇzstv´ı dat na ˇcten´ı po-sloupnosi nˇekolika menˇs´ıch datov ´ych blok ˚u. V pr ˚ubˇehu plnˇen´ı z´asobn´ık ˚u sekvenˇcn´ım ˇcten´ım z disku, jsou jiˇz nˇekter´e z´asobn´ıky naplnˇeny a mohou b ´yt pouˇzity k dalˇs´ımu zpra-cov´an´ı. Nev ´yhodou je, ˇze ˇcten´ı nem ˚uˇze zaˇc´ıt dˇr´ıve, dokud nen´ı pr´azdn ´ych m-1 z´asobn´ık ˚u patˇr´ıc´ıch ke stejn ´ym skupin´am, operaˇcn´ı pamˇet’ tedy nen´ı plnˇe vyuˇzita.

V pr ˚ubˇehu sluˇcovac´ı f´aze jsou data ˇctena v odliˇsn´em poˇrad´ı, neˇz v jak´em byla za-pisov´ana ve f´azi tvorby skupin. Ve f´azi pro tvorbu skupin se totiˇz skupiny zapisuj´ı na po sobˇe jdouc´ı m´ısta na disku, narozd´ıl od spojovac´ı f´aze, kde jsou data ˇctena v urˇcit´em poˇrad´ı, kter´e z´avis´ı na poˇrad´ı vstupn´ıch z´aznam ˚u. To m´a dopad na celkov´e pˇr´ıstupov´e n´aklady na disk, zvyˇsuje se totiˇz vyhled´avac´ı doba. Metoda prokl´adan´e rozvrˇzen´ı [6] umist’uje z´aznamy z r ˚uzn ´ych skupin do souvisl ´ych pozic podle algoritmu robin-round. Je zaloˇzena na oˇcek´av´an´ı, ˇze m´ısto nov´eho z´aznamu je bl´ıˇze k poˇrad´ı, v jak´em budou ˇcteny z´aznamy z disku a takto sniˇzuje vyhled´avac´ı ˇcas. Pˇredstavuje vˇsak reˇzii v pr ˚ubˇehu f´aze pro tvorbu skupin.

3.3.1 Pl ´anov ´an´ı ˇcten´ı

Kaˇzd´a skupina je rozdˇelena do blok ˚u o d´elce rovnaj´ıc´ı se velikosti vyrovn´avac´ı pamˇeti. Uloˇzen´ım maxim´aln´ı kl´ıˇcov´e hodnoty z kaˇzd´eho bloku dat jsme schopni urˇcit poˇrad´ı, ve kter´em budou bloky poˇzadov´any v pr ˚ubˇehu spojovac´ı f´aze. Toto poˇrad´ı se naz ´yv´a posloupnost spotˇreby [6]. Ukl´ad´an´ı maxim´aln´ı kl´ıˇcov´e hodnoty nepˇredstavuje v ´yznamnou reˇzii, protoˇze lze prov´est v hlavn´ı pamˇeti. Tyto kl´ıˇce by mˇely b ´yt setˇr´ıdˇeny, coˇz je moˇzno prov´est, kdyˇz se zaˇc´ın´a zapisovat posledn´ı skupina na disk (v pr ˚ubˇehu tvorby skupin) nebo bˇehem pˇredch´azej´ıc´ı spojovac´ı f´aze.

Pokud jsou bˇehem spojovac´ı f´aze dostupn´e nˇejak´e extra z´asobn´ıky, lze je pouˇz´ıt pro ˇcten´ı datov ´ych blok ˚u, kter´e nejsou aktu´alnˇe potˇrebn´e v nˇejak´e ˇc´asti spojov´an´ı. ˇCten´ı tˇechto blok ˚u nepˇredstavuje rotaˇcn´ı nebo vyhled´avaj´ıc´ı zpoˇzdˇen´ı, jelikoˇz bloky jsou v po sobˇe jdouc´ıch pozic´ıch. Posloupnost spotˇreby m ˚uˇzeme pouˇz´ıt k urˇcen´ı, kter´e bloky bu-dou potˇrebn´e v n´asleduj´ıc´ıch f´az´ıch, naˇc´ıst je za n´ızk´e n´aklady a urychlit tak spojovac´ı ˇc´ast.

Tento probl´em lze formulovat n´asledovnˇe [6]: Bud’ n poˇcet skupin, T poˇcet datov ´ych blok ˚u, B poˇcet z´asobn´ık ˚u. Pak C = {C1, C2, ..., CT} je blok posloupnosti spotˇreby, R =

{R1, R2, ..., RT} je ˇctec´ı sekvence, L je mapovac´ı funkce mezi datov ´ymi bloky a

pozi-cemi disku, kter´e jsou oznaˇceny ˇc´ısly 1, 2, ..., T. Kaˇzd´a ˇctec´ı sekvence R je charakteri-zov´ana svou cenou, kter´a je rovna souˇctu celkov´eho vyhled´avac´ıho ˇcasu a celkov´eho pˇrenosov´eho ˇcasu potˇrebn´eho ke ˇcten´ı datov ´ych blok ˚u v poˇrad´ı urˇcen´em R. Vzhledem k tomu, ˇze kaˇzd´a ˇctec´ı sekvence m´a stejou dobu pˇrenosu, v ´ybˇer nejlepˇs´ı sekvence je zaloˇzen na v ´ypoˇctu hledac´ıho ˇcasu. ˇCtec´ı sekvence nav´ıc mus´ı spl ˇnovat dalˇs´ı podm´ınku - v kaˇzd´e f´azi mus´ı b ´yt uchov´an nejm´enˇe jeden blok dat z kaˇzd´e skupiny v jednom z dostupn ´ych z´asobn´ık ˚u. Sekvence spl ˇnuj´ıc´ı tuto podm´ınku se naz ´yv´a provediteln´a. Mus´ıme tedy naj´ıt proveditelnou sekvenci, kter´a m´a minim´aln´ı hledac´ı ˇcas.

Lze snadno odvodit, ˇze probl´em nalezen´ı optim´aln´ı provediteln´e ˇctec´ı sekvence je ekvivalentn´ı s probl´emem obchodn´ıho cestuj´ıc´ıho, proto m ˚uˇze b ´yt navrˇzeno jen heuris-tick´e ˇreˇsen´ı. Heuristika je zaloˇzen´a na um´ıstˇen´ı kaˇzd´eho Ci ´udaje z bloku posloupnosti

(29)

spotˇreby C uvnitˇr ˇctec´ı sekvence R v pozici, kter´a minimalizuje vyhled´avac´ı ˇcas. Ten se vypoˇcte podle L(Ri)pozice disku, kde jsou uloˇzeny ´udaje o ˇctec´ı sekvenci. Aby byla ˇctec´ı

sekvence provediteln´a, je udrˇzov´ana dalˇs´ı sekvence F. J-t ´y ´udaj sekvence F pˇredstavuje poˇcet voln ´ych z´asobn´ık ˚u pˇred pˇreˇcten´ım ´udaje Rjve ˇctec´ı sekvenci. Pokud je Civloˇzeno

na pozici p ˇctec´ı sekvence, dostaneme Rp, kde p < i, pak je pro jeho uloˇzen´ı potˇreba

dalˇs´ıho z´asobn´ıku. Proto je Fj zmenˇseno o 1, kdyˇz p ≤ j < i, ve smyslu, ˇze pro bloky

Rp, ..., Ri−1bude o jeden z´asobn´ık m´enˇe, neˇz kdyˇz zaˇcaly b ´yt ˇcteny. Pokud je Fj = 0pro

dan´e j, pak ˇz´adn ´y blok za j z posloupnosti spotˇreby nem ˚uˇze b ´yt um´ıstˇen pˇred j ve ˇctec´ı sekvenci. Promˇenn´a s zaznamen´av´a posledn´ı hodnotu j, kde je Fj = 0.

Algoritmus 2: Uk´azka pseudok ´odu algoritmu posloupnosti spotˇreby R1:=C1; s:=1; for j:=1 to T do Fj:=B-n; for i:=2 to T do p:=i; for j:=s to i-1 do

if Rj se nach´az´ı na stejn´e stopˇe na disku jako CiAND L(Ri) > L(Ci) then

p:=j; break;

for k:=i downto p+1 do

Rk:= Rk− −;

Fk:= Fk−1− −;

if Fk=0 AND s¡=k then

s:=k+1; Rp:=Ci;

Popsan ´y algoritmus m´a sloˇzitost O(T2)a m ˚uˇze b ´yt spuˇstˇen, dokud je na disku uloˇzena posledn´ı skupina. Metoda pl´anov´an´ı ˇcten´ı s pouˇzit´ım posloupnosti spotˇreby dok´azala pˇrekonat metody dvojit´eho vyrovn´av´an´ı i prognostickou metodu [6].

3.3.2 Seskupov ´an´ı blok ˚u

Tato metoda se snaˇz´ı o nalezen´ı heuristick´eho ˇreˇsen´ı probl´emu optim´aln´ı ˇctec´ı cesty. Je zaloˇzena na seskupen´ı takov´eho mnoˇzstv´ı sousedn´ıch blok ˚u dat ze stejn´e skupiny, jak je jen moˇzn´e. Nˇekolik sousedn´ıch blok ˚u ze stejn´e skupiny tvoˇr´ı celek, kter ´y m ˚uˇze b ´yt pˇreˇcten sekvenˇcnˇe. ˇC´ım menˇs´ı je poˇcet skupin, t´ım m´enˇe vyhled´avac´ıho ˇcasu bude potˇreba bˇehem spojov´an´ı. Tato ˇctec´ı sekvence (celek) je provediteln´a, pokud je v pr ˚ubˇehu spojovac´ı ˇc´asti pˇreˇcten kaˇzd ´y blok pr´avˇe jednou. Metoda pro stanoven´ı proveditelnosti ˇctec´ı sekvence je zaloˇzena na poˇctu voln ´ych z´asobn´ık ˚u, F. Fi je rovno poˇctu voln ´ych

(30)

22

z´asobn´ıkov ´ych str´anek po pˇreˇcten´ı i-t´eho celku. Velikosti celk ˚u jsou oznaˇceny L = {L1, L2, ..., LN}

pro dan´e N [6].

Algoritmus 3: Uk´azka pseudok ´odu algoritmu seskupov´an´ı blok ˚u R:=C;

//ˇctec´ı sekvence se inicializuje podobnˇe jako posloupnost spotˇreby

for i:=1 to T do

Li:=1;

//nastaven´ı prvotn´ı velikosti celku lastC1:=n;

for i:=n+1 to T do

for j:=lastC1 downto 1 do

if Rj.runNumber=Ri.runNumber then

k:=j; break;

if lze Rizkombinovat s RK pˇri zachov´an´ı proveditelnosti then

LK++;

else

//Rise stane nov ´ym celkem lastC1++;

RlastC1++;

N:=lastC1;

Seskupov´an´ı blok ˚u je nejefektivnˇejˇs´ı metodou ze vˇsech variant pro zlepˇsen´ı spojo-vac´ıch algoritm ˚u. Oproti metodˇe pl´anov´an´ı ˇcten´ı, kter´a je druh´a nejlepˇs´ı, dosahuje n´ar ˚ust v ´ykonu 30%. Nav´ıc je schopna vyuˇz´ıt jiˇz ˇc´asteˇcnˇe pˇredtˇr´ıdˇen´a data [1].

Extern´ı mergesort je doposud nejlepˇs´ı tˇr´ıd´ıc´ı algoritmus pro vnˇejˇs´ı tˇr´ıdˇen´ı [1], zde uveden´e optimalizace jeˇstˇe d´ale vylepˇsuj´ı jeho v ´ykonnost. Obecnˇe jde o snahu minimali-zovat prodlevu pˇri ˇcten´ı a ukl´ad´an´ı na pevn ´y disk (ˇci ji co nejv´ıce vyuˇz´ıt k dalˇs´ı optima-lizaci) nebo pˇrekr ´yv´an´ı procesorov´eho a vstupnˇe/v ´ystupn´ıho ˇcasu.

(31)

4

Komponenta perzistentn´ıho pole

4.1 Popis komponenty

Pˇri ´uvahami nad anal ´yzou tˇr´ıdˇen´ı dat na extern´ım ´uloˇziˇsti podle popsan ´ych algoritm ˚u se n´am nask ´yt´a nˇekolik probl´em ˚u. Mezi jeden z nich patˇr´ı jak ´ym zp ˚usobem navrhnout a implementovat vyrovn´avac´ı pamˇet’ pro ˇcten´ı a z´apis soubor ˚u. Jelikoˇz je nutno m´ıt kon-trolu nad volbou velikost´ı jednotliv ´ych vyrovn´avac´ıch pamˇet´ı, je vyrovn´avac´ı pamˇet’ v souborov´em syst´emu operaˇcn´ıho syst´emu nevyhovuj´ıc´ı. Rozhodl jsem se vyuˇz´ıt ˇreˇsen´ı, kter´e je jiˇz naimplementov´ano a vˇsechny potˇrebn´e podm´ınky spl ˇnuje - perzistentn´ı pole. Perzistentn´ı pole se z hlediska program´atora tv´aˇr´ı jako dynamick´e pole vektor ˚u, kter´e vˇsechna sv´a data samostatnˇe ukl´ad´a do extern´ıho souboru a napodobuje sv ´ym chov´an´ım re´aln ´y souborov ´y syst´em operaˇcn´ıho syst´emu. Hlav´ı v ´yhoda perzistentn´ıho pole na-rozd´ıl od bˇeˇzn´eho datov´eho souboru uloˇzen´em v souborov´em syst´emu spoˇc´ıv´a ve vlastn´ı vyrovn´avac´ı pamˇet’ cache, kter´a umoˇz ˇnuje l´epe ˇr´ıdit, co bude uloˇzeno na pevn´em disku a co v hlavn´ı pamˇeti. Vˇsechny tˇr´ıdy implementuj´ıc´ı toto pole jsem pˇrevzal z aplikaˇcn´ıho r´amce ATOM implementovan ´y datab´azovou skupinou na Katedˇre informatiky Fakulty elektrotechniky a informatiky, Vysok´e ˇskoly B´a ˇnsk´e - Technick´e univerzity Ostrava.

Nyn´ı jiˇz k samotn ´ym tˇr´ıd´am implementuj´ıc´ım perzistentn´ı pole. To v sobˇe ukl´ad´a vektory typu zdˇedˇen´eho ze tˇr´ıdy cBasicType, v n´asleduj´ıc´ıch pˇr´ıkladech i v t´eto pr´aci budu pouˇz´ıvat prvky, jeˇz reprezentuje tˇr´ıda cNTreeTuple NoEncodeType. Nezbytnou souˇc´ast´ı je ˇsablona cSizeInfo, kter´a zajiˇst’uje spr´avn ´y v ´ypoˇcet velikosti poloˇzky, d ˚uleˇzit ´y pˇredevˇs´ım u sloˇzitˇejˇs´ıch typ ˚u. Parametrizuje se poloˇzkami konkr´etn´ıho typu zdˇedˇen´e z jiˇz zmi ˇnovan´e tˇr´ıdy cBasicType. Pro vkl´ad´an´ı prvk ˚u typu cNTreeTuple je pˇripraven´a tˇr´ıda cNTupleSizeInfo parametrizuj´ıc´ı ˇsablonu cSizeInfo typem cNTreeTuple. Tato tˇr´ıda obsahuje informace i pro zde pouˇz´ıvan ´y typ prvk ˚u cNTreeTuple NoEncodeType.

4.2 Pˇr´ıklad pr ´ace s perzistentn´ım polem

Pro pr´aci se samotn ´ym perzistentn´ım pole potˇrebujeme vytvoˇrit nˇekolik pomocn ´ych ob-jekt ˚u a definovat parametry pˇri jejich vytv´aˇren´ı:

• Nejprve je tˇreba definovat typ vkl´adan ´ych prvk ˚u. V n´asleduj´ıc´ıch pˇr´ıkladech bu-dou jednotliv´e prvky typu cNTreeTuple NoEncodeType, jednotliv´e vektory mohou m´ıt promˇennou d´elku, tedy kaˇzd ´y z nich nemus´ı m´ıt d´elku urˇcenou dimenz´ı. Po-sledn´ı definic´ı typu tPersistentArray jen vloˇz´ıme pˇredchoz´ı typy do ˇsablony sa-motn´eho perzistentn´ıho pole.

• D´ale je tˇreba popisovaˇc m´ısta, pˇri jehoˇz vytv´aˇren´ı vkl´ad´ame do kontruktoru hod-noty maxim´aln´ı dimenze vektor ˚u a jejich datov ´y typ, dˇed´ıc´ı ze tˇr´ıdy cDataType. Popisovaˇc m´ısta je nov´a instance tˇr´ıdy zdˇedˇen´e z obecn´eho popisovaˇce cTreeSpa-ceDescriptor. V tomto pˇr´ıpadˇe tedy bude maxim´aln´ı dimenze vektor ˚u 10 prvk ˚u a jednotliv´e prvky vektoru budou neznam´enkov´e celoˇc´ıseln´e, viz ˇr´adek 7 ve zdro-jov´em k ´odu 1.

(32)

24

• Hlaviˇcka perzistentn´ıho pole je zdˇedˇen´a ze tˇr´ıdy cHeader. Jak jiˇz n´azev napov´ıd´a, jde o hlaviˇcku ekvivalentn´ı ke zvolen´emu typu prvku i samotn´eho perzistentn´ıho pole, tj. cPersistentArrayHeader VarLen. Jako parametry konstruktoru vkl´ad´am informace o voln´em m´ıstˇe, kter´emu d´ale pˇred´am dˇr´ıve vytvoˇren ´y popisovaˇc m´ısta. Tato infor-mace o voln´em m´ıstˇe dˇed´ı ze z´akladn´ı tˇr´ıdy cSizeInfo a odpov´ıd´a zvolen´emu typu prvku pole. Druh ´y vkl´adan ´y parametr je velikost uzlu vkl´adan´eho prvku, tˇret´ı pak urˇcuje velikost bloku, v podstatˇe jde velikost alokaˇcn´ı jednotky, zde tedy 4kB. • Nyn´ı jiˇz m ˚uˇzeme vytvoˇrit samotn´e perzistentn´ı pole, jako parametr konstruktoru

pˇred´av´am dˇr´ıve vytvoˇrenou hlaviˇcku, viz ˇr´adek 15 ve zdrojov´em k ´odu 1.

• Pro ˇcten´ı vektor ˚u z pole pouˇz´ıv´am kontext, slouˇz´ıc´ı k uloˇzen´ı informac´ı potˇrebn ´ych pro pr´aci s perzistentn´ım polem s promˇennou d´elkou vektor ˚u. Sleduje uzel, aktu´aln´ı m´ısto v uzlu a aktu´aln´ı poloˇzku. Ukl´ad´a tak´e dalˇs´ı pomocnou pamˇet’. Jde o tˇr´ıdu zdˇedˇenou ze z´akladn´ı tˇr´ıdy cDataStructureContext. Jej´ı typ opˇet odpov´ıd´a typu per-zistentn´ıho pole. Jako parametr kontruktoru vkl´ad´am hlaviˇcku, kter´a obsahuje vˇsechny potˇrebn´e ´udaje pro jeho spr´avnou inicializaci.

Nyn´ı chv´ıli m´ame vytvoˇreny a inicializov´any vˇsechny potˇrebn´e objekty a m ˚uˇzeme zaˇc´ıt pracovat se samotn ´ym polem. Vstupn´ı soubor pole naˇcteme metodou Open() (ˇr´adek ˇc. 21), kde jako parametry uvedeme n´azev otev´ıran´eho souboru, d´ale logickou hodnotu, m´a-li b ´yt dan ´y soubor otevˇren jen pro ˇcten´ı a velikost vyrovn´avac´ı pamˇeti v poˇctech blok ˚u. Dalˇs´ı metodou OpenContext() (ˇr´adek ˇc. 23) otevˇru kontext dan´eho pole na indexu a pozici, kter´e mi urˇcuj´ı prvn´ı dva parametry. Zde je to logicky zaˇc´atek cel´eho pole. D´ale v jednoduch´em cyklu vypisuji vˇsechny vektory a jejich jednotliv´e prvky ze souboru per-zistentn´ıho pole, dokud kontext nedojde na jeho konec. Metodou Advance() (ˇr´adek ˇc. 29) posunu kontext z aktu´aln´ıho vektoru vˇzdy o jeden d´ale, pokud kontext dojde na ko-nec souboru, vrac´ı metoda logickou hodnotu false. Po ukonˇcen´ı pr´ace s kontextem staˇc´ı zavolat metodu CloseContext() (ˇr´adek ˇc. 31), obdobnˇe zavol´ame po skonˇcen´ı pr´ace s per-zistentn´ım polem metodu Close() (ˇr´adek ˇc. 32).

Nyn´ı se jiˇz pod´ıvejme na samotn ´y zdrojov ´y k ´od:

1 void Ukazka::Vypis ze souboru(){

2

3 typedef cNTreeTuple NoEncodeType Type;

4 typedef cPersistentArrayNode VarLen<Type> tNode;

5 typedef cPersistentArray VarLen<Type, tNode> tPersistentArray;

6

7 cNTreeSpaceDescriptor ∗popisovac =new cNTreeSpaceDescriptor(10, new cUIntType());

8

9 cPersistentArrayHeader VarLen<Type> ∗hlavicka =

10 new cPersistentArrayHeader VarLen<Type>(

11 new cNTupleSizeInfo(popisovac),

12 tNode::GetNodeExtraSize(), 13 4096);

14

15 tPersistentArray ∗pole =new tPersistentArray(hlavicka) ;

16

(33)

18 new cPersistentArrayContext VarLen<Type>(hlavicka); 19 20 21 pole−>Open(”Output.dat”,true, 8); 22 23 pole−>OpenContext(0, 0, kontext); 24 25 do{ 26 27 kontext−>GetItem()−>Print(”\n”); 28 29 }while(pole−>Advance(kontext)); 30 31 pole−>CloseContext(kontext); 32 pole−>Close(); 33 34 delete pole; 35 delete kontext; 36 delete hlavicka; 37 delete popisovac; 38 39 }

V ´ypis 1: Uk´azka v ´ypisu vektor ˚u ze souboru perzistentn´ıho pole V ´ypis z uveden´eho zdrojov´eho k ´odu bude podobn ´y tomuto:

(34, 8, 28, 68, 3, 29),realSize: 6 (0, 51, 70, 19, 8, 18, 16, 14, 99, 17),realSize: 10 (1, 23, 71, 36, 61, 57, 77, 16),realSize: 8 (79, 72, 77, 34, 69, 12, 1, 70, 55, 41),realSize: 10 (1, 39, 80, 81, 24, 90, 94, 82, 94, 91),realSize: 10 (2, 35, 9, 81, 11, 92, 30),realSize: 7

V ´ypis 2: V ´ystup z metody v ´ypisu vektor ˚u ze souboru perzistentn´ıho pole

Na druh´em pˇr´ıkladu si uk´aˇzeme jednoduch´e vkl´ad´an´ı vektor ˚u do souboru. Vyuˇzijeme typy a objekty pops´any v pˇr´ıkladˇe 1, novˇe n´am pˇribyde objekt prvek (ˇr´adek ˇc. 20), kter ´y zde pˇredstavuje vektor ukl´adan ´y do perzistentn´ıho pole. Jako parametr kontruktoru zde pˇred´av´am hlaviˇcku perzistentn´ıho pole.

Nov ´y soubor perzistentn´ıho pole vytvoˇr´ıme metodou Create() (ˇr´adek ˇc. 18), kde jako parametry vloˇz´ıme n´azev souboru, kter ´y se m´a vytvoˇrit a velikost vyrovn´avac´ı pamˇeti v poˇctech blok ˚u. Metodou SetValue() (ˇr´adek ˇc. 24) nastavujeme jednotliv´e poloˇzky vek-toru, zde neznam´enkov´a cel´a ˇc´ısla. Prvn´ım parametrem metody je pozice ve vekvek-toru, kterou chceme nastavit, t´ım druh ´ym pak samotn´a hodnota. Metoda AddItem() (ˇr´adek ˇc. 28) pak vytvoˇren ´y prvek uloˇz´ı do perzistentn´ıho pole. Tato metoda vrac´ı index a po-zici pr´avˇe vloˇzen´eho prvku, tˇret´ım parametrem je prvek, kter ´y chceme vloˇzit. Pro v ´ypis prvku slouˇz´ı metoda Print() (ˇr´adek ˇc. 29), kde vloˇzen ´y parametr pln´ı funkci oddˇelovaˇce. Stejnˇe jako pˇri ˇcten´ı z pole je tˇreba jej po ukonˇcen´ı pr´ace zavˇr´ıt metodou Close() (ˇr´adek ˇc. 33).

(34)

26

Tento k ´od vytvoˇr´ı perzistentn´ı pole o 10 prvc´ıch, kde na nultou pozici uloˇz´ı jeho poˇrad´ı od 0 a na dalˇs´ıch pozic´ıch postupnˇe ukl´ad´a druh´e mocniny aˇz do hodnoty aktu´aln´ı pozice. V ´ysledek bude zaps´an v souboru mojepole.dat.

1 void Ukazka::Zapis do souboru(){

2

3 typedef cNTreeTuple NoEncodeType Type;

4 typedef cPersistentArrayNode VarLen<Type> tNode;

5 typedef cPersistentArray VarLen<Type, tNode> tPersistentArray;

6

7 unsigned int index, pozice;

8 cNTreeSpaceDescriptor ∗popisovac =new cNTreeSpaceDescriptor(10, new cUIntType());

9

10 cPersistentArrayHeader VarLen<Type> ∗hlavicka =

11 new cPersistentArrayHeader VarLen<Type>(

12 new cNTupleSizeInfo(popisovac),

13 tNode::GetNodeExtraSize(), 14 4096);

15

16 tPersistentArray ∗pole =new tPersistentArray(hlavicka) ;

17

18 pole−>Create(”mojepole.dat”, 8); 19

20 cNTreeTuple ∗prvek =new cNTreeTuple(popisovac);

21

22 for(unsigned int i=0; i <10; i++){

23 for(unsigned int j=1; j<=i; j ++){

24 prvek−>SetValue(0, i); 25 prvek−>SetValue(j, j∗j); 26 }

27

28 pole−>AddItem(index, pozice, ∗prvek); 29 prvek−>Print(”\n”); 30 prvek−>Clear(); 31 } 32 33 pole−>Close(); 34 35 delete prvek; 36 delete pole; 37 delete hlavicka; 38 delete popisovac; 39 40 }

V ´ypis 3: Uk´azka z´apisu vektor ˚u do souboru perzistentn´ıho pole V ´ypis z uveden´eho zdrojov´eho k ´odu bude n´asleduj´ıc´ı:

() ,realSize: 0 (1, 1),realSize: 2 (2, 1, 4),realSize: 3 (3, 1, 4, 9),realSize: 4 (4, 1, 4, 9, 16),realSize: 5 (5, 1, 4, 9, 16, 25),realSize: 6

(35)

(6, 1, 4, 9, 16, 25, 36),realSize: 7 (7, 1, 4, 9, 16, 25, 36, 49),realSize: 8 (8, 1, 4, 9, 16, 25, 36, 49, 64),realSize: 9 (9, 1, 4, 9, 16, 25, 36, 49, 64, 81),realSize: 10

V ´ypis 4: V ´ystup z metody v ´ypisu vektor ˚u ze souboru perzistentn´ıho pole

Jak lze vidˇet z pˇredchoz´ıch pˇripad ˚u, samotn´a pr´ace s perzistentn´ım polem je intu-itivn´ı a velice podobn´e pr´aci s bˇeˇzn ´ymi soubory. Pˇri vytv´aˇren´ı pol´ı a potˇrebn ´ych typ ˚u je dobr´e b ´yt pozorn ´y a pˇr´ıpadnou alokaci prvk ˚u prov´adˇet mimo ˇcasto pouˇz´ıvan´e me-tody. Uˇsetˇr´ıme tak nemal´e mnoˇzstv´ı pamˇeti, jelikoˇz C++ nem´a tak propracovanou spr´avu pamˇeti jako modernˇejˇs´ı jazyky jako C# nebo Java. Napˇr. opakovanou alokaci jednoho prvku v cyklu ˇreˇs´ı alokac´ı nov´eho m´ısta na haldˇe a pamˇet’ potˇrebn´a k alokaci jednoho prvku tak m ˚uˇze v extr´emn´ım pˇr´ıpadˇe nar ˚ust na souˇcin velikosti prvku a d´elky cyklu!

(36)
(37)

5

Anal ´yza a n ´avrh komponenty pro extern´ı tˇr´ıd ˇen´ı prvk ˚

u

5.1 Specifikace poˇzadavk ˚u

M ´ym ´ukolem bylo navrhnout a implementovat komponentu pro tˇr´ıdˇen´ı prvk ˚u ze struk-tury perzistentn´ıho pole vyuˇz´ıvaj´ıc´ı jen pˇredem definovanou velikost hlavn´ı pamˇeti. Po prostudov´an´ı teorie t ´ykaj´ıc´ı se tˇr´ıdˇen´ı dat na extern´ım ´uloˇziˇsti jsem musel vz´ıt v potaz samotn´a data, nad kter ´ymi bude pozdˇeji algoritmus bˇeˇzet. Jelikoˇz jde o data s relativnˇe velk ´ym hodnotov ´ym rozsahem, zvolil jsem ve sv´e implementaci k algoritmu pro tˇr´ıdˇen´ı dat na extern´ım ´uloˇziˇsti, extern´ımu mergesortu, optimalizaci posloupnosti spotˇreby, viz. kapitola 3.3. Prvn´ı f´aze algoritmu vyuˇz´ıv´a sch´ema naˇcti-setˇrid’-uloˇz popsan´e v kapitole 3.2.1.

Celou komponentu bylo nutno navrhnout obecnˇe, jelikoˇz komponenta perzistentn´ıho pole je navrhnov´ana pro mnoˇzstv´ı typ ˚u, kde kaˇzd ´y z nich rozˇsiˇruje z´akladn´ı tˇr´ıdu typu o metody nutn´e ke spr´avn´emu chodu konkr´etn´ıho typu. Mnou navrˇzen´a komponenta tedy mus´ı umˇet tˇr´ıd´ıt typy rozˇsiruj´ıci z´akladn´ı tˇr´ıdu cDataType, jin ´ymi slovy, tˇr´ıdˇen ´y typ bude mou tˇr´ıdu parametrizovat.

Komponenta mus´ı spl ˇnovat:

• Tˇr´ıdit prvky rozˇsiˇruj´ıc´ı tˇr´ıdu cDataType, resp. jej´ıho potomka cBasicType. • Pˇri tˇr´ıdˇen´ı pouˇz´ıvat jen pˇredem zn´amou velikost hlavn´ı pamˇet’i.

• Komponentu optimalizovat pro re´aln´a data, nad kter ´ymi bude bˇeˇzˇet.

• Pro testov´an´ı implementovat metodu pro naˇc´ıt´an´ı dat z textov´eho souboru, d´ale vhodn ´ym zp ˚usobem umoˇznit zad´avat jednotliv´e parametry tˇr´ıdˇen´ı.

Jako omezen´ı se aˇz v pr ˚ubˇehu implementace uk´azala b ´yt nespr´avnˇe pracuj´ıc´ı vy-rovn´avac´ı pamˇet perzistentn´ıho pole, kv ˚uli kter´e bylo nutno ´uplnˇe odstranit rekurzi ve druh´e ˇc´asti mergesortu a nahradit ji upraven ´ym nerekurzivn´ım algoritmem. Bylo tedy nutno upravit anal ´yzu a n´aslednou imlementaci tak, abych se tomuto probl´emu vyva-roval. I tak jsem se ale nevyhnul omezen´ı v podobˇe nadmˇernˇe nar ˚ustaj´ıc´ıch n´aroc´ıch na dalˇs´ı hlavn´ı pamˇet’ pˇri bˇehu v ´ysledn´e aplikace.

Dostupn´a pamˇet’ pˇredstavuje pro algoritmus v prvn´ı ˇc´asti mnoˇzstv´ı hlavn´ı pamˇeti (v bloc´ıch definovan ´ych pˇri vytv´aˇren´ı hlaviˇcek pole, viz ˇr´adek 9 ve zdrojov´em k ´odu 1) pouˇzitou ke tˇr´ıdˇen´ı jednotliv ´ych skupin. Velikost skupin v prvn´ı f´azi algoritmu je tedy rovna velikosti dostupn´e hlavn´ı pamˇeti. Ve druh´e f´azi n´am velikost hlavn´ı pamˇeti definuje maxim´aln´ı poˇcet skupin otevˇren ´ych souˇcasnˇe pˇri bˇehu sl´evac´ı ˇc´asti algotimu. Vstupn´ı a v ´ystupn´ı z´asobn´ık o kter ´ych jsme mluvili v ´uvodu zde nejsou potˇreba, tuto reˇzii za n´as ˇreˇs´ı samotn´e perzistentn´ı pole.

5.2 Specifikace pomoc´ı pˇr´ıpadu uˇzit´ı

Diagram pˇr´ıpadu uˇzit´ı, tzv. Use Case, n´am popisuje, jak akt´eˇri, stoj´ıc´ı vnˇe syst´emu, pra-cuj´ı s jednotliv ´ymi funkcemi syst´emu.

(38)

30

Obr´azek 3: Diagram pˇr´ıpadu uˇzit´ı syst´emu

V tomto pˇr´ıpadˇe jde o velice jednoduch ´y model, kdy uˇzivatel, pracuj´ıc´ı se syst´emem, pouˇz´ıv´a jen se samotnou komponentou pro testov´an´ı tˇr´ıdˇen´ı, kter´a vyuˇz´ıv´a tˇr´ıdy pro tˇr´ıdˇen´ı na extern´ım ´uloˇziˇsti a tˇr´ıdy perzistentn´ıho pole. Komponenty pro tˇr´ıdˇen´ı samozˇrejmˇe tak´e vyuˇz´ıvaj´ı tˇr´ıdy perzistentn´ıho pole.

5.3 Tˇr´ıdn´ı diagram

Pomoc´ı tˇr´ıdn´ıho diagramu (Obr´azek 4) je zde nast´ınˇena statick´a struktura syst´emu prostˇrednictv´ım jednotliv ´ych tˇr´ıd a vz´ajemn ´ych vztah ˚u mezi nimi:

• SortArray je ˇsablona implementuj´ıc´ı samotn´e tˇr´ıdˇen´ı dat za pomoc´ı omezen´eho mnoˇzstv´ı hlavn´ı pamˇeti. Parametrizuje se konkr´etn´ı typem, pˇredstavuj´ıc´ı tˇr´ıdˇen ´y prvek, dˇed´ıc´ı ze tˇr´ıdy cBasicType. Jsou zde jednotliv´e metody pro tˇr´ıdˇen´ı i d´ale po-psan´a optimalizace.

• ˇsablona RunInfo slouˇz´ı k ukl´ad´an´ı ´udaj ˚u o jednotliv ´ych setˇr´ıdˇen ´ych skupin´ach vzni-kaj´ıc´ıch v prvn´ı ˇc´asti algoritmu. Zaznamen´av´a se zde index a pozice posledn´ıho

(39)

prvku skupiny, jej´ı maxim´aln´ı a minim´aln´ı prvek a logickou hodnotu vypov´ıdaj´ıc´ı o pouˇzit´ı dan´e skupiny ve druh´e ˇc´asti algoritmu.

• tˇr´ıda ArrayTest je tˇr´ıdou pro testov´an´ı v ´yˇse uveden ´ych tˇr´ıd, jej´ı souˇc´ast´ı je gener´ator n´ahodn ´ych vektor ˚u a naˇc´ıt´an´ı textov ´ych soubor ˚u. Uˇzivatel s touto tˇr´ıdou komuni-kuje pˇres rozhran´ı pˇr´ıkazov´e ˇr´adky, kde zad´av´a odpov´ıdaj´ıc´ı parametry.

• tˇr´ıda cNTreeTuple NoEncodeType zde pˇredstavuje konkr´etn´ı tˇr´ıdˇen ´y prvek, jedin´a vazba na nˇej bude ze samotn´e testovac´ı tˇr´ıdy.

• ˇsablona cPersistentArrayNode VarLen pˇredstavuje vektor vkl´adan ´y do perzistentn´ıho pole, parametrizuje se konkr´etn´ım tˇr´ıdˇen ´ym typem.

• ˇsablona cPersistentArray VarLen odpov´ıd´a jiˇz zmi ˇnovan´emu konkr´etn´ımu perzis-tentn´ımu poli. Parametrizuje se konkr´etn´ım tˇr´ıdˇen ´ym typem a jemu odpov´ıdaj´ıc´ım uzlem.

Uˇzivatel bude s aplikac´ı kominukovat prostˇrednictv´ım pˇr´ıkazov´e ˇr´adky, kde bude zad´avat potˇrebn´e parametry. Samotn´a tˇr´ıda ArrayTest v sobˇe zahrnuje jak generov´an´ı n´ahodn ´ych vektor ˚u dle uˇzivatelem zadan ´ych parametr ˚u, tak i naˇc´ıt´an´ı textov ´ych sou-bor ˚u a jejich n´asledn´e pˇreveden´ı do perzistentn´ıho pole tak, aby danou mnoˇzinu dat bylo moˇzno d´ale setˇr´ıdit. Setˇr´ıdˇen´ı perzistentn´ıho pole pak probˇehne zavol´an´ım metody Sort() ze tˇr´ıdy SortArray s odpov´ıdaj´ıc´ımi parametry.

(40)

32

(41)

6

Implementace

C´ılem t´eto kapitoly je popsat samotnou implementaci vych´azej´ıc´ı z pˇredchoz´ı anal ´yzy a n´avrhu, popsat nejd ˚uleˇzitˇejˇs´ı metody komponenty pro tˇr´ıdˇen´ı prvk ˚u na extern´ım ´uloˇziˇsti a jejich optimalizaci. Aplikace je naprogramov´ana jako konzolov´a v jazyce C++, pˇred´av´an´ı informac´ı a pˇrep´ınaˇc ˚u je realizov´ano pomoc´ı voliteln ´ych parametr ˚u, kter ´ym se podrobnˇeji vˇenuji v pˇr´ıloze A.

V dalˇs´ıch kapitol´ach si pˇredstav´ıme implementovan´e tˇr´ıdy, jejich v ´yznam a nejd ˚uleˇzitˇejˇs´ı metody.

6.1 Tˇr´ıda ArrayTest

Tˇr´ıda ArrayTest slouˇz´ı k otestov´an´ı n´ıˇze popsan ´ych ˇsablon pro tˇr´ıdˇen´ı prvk ˚u na extern´ım ´uloˇziˇsti, obsahuje metodu main, kter´a je po spuˇstˇen´ı aplikace vol´ana. Pro optim´aln´ı tes-tov´an´ı m´a uˇzivatel k dispozici jak vygenerov´an´ı n´ahodn ´ych vektor ˚u pole podle pˇredem nastaven ´ym parametr ˚u tak moˇznost naˇcten´ı textov´eho souboru s jednotliv ´ymi vektory, kde kaˇzd ´y ˇr´adek odpov´ıd´a jednomu vektoru a prvky kaˇzd´eho vektoru jsou oddˇeleny ˇc´arkou (dalˇsi popis je uveden v pˇr´ıloze A). Po vygenerov´an´ı, resp. naˇcten´ı dat, jsou vektory uloˇzeny do struktury perzistentn´ıho pole pˇripraveny na samotn´e tˇr´ıdˇen´ı. Ty-pem tˇr´ıdˇen´eho prvku parametrizujeme obˇe potˇrebn´e ˇsablony a vol´ame potˇrebn´e me-tody. Kromˇe n´azvu extern´ıho souboru perzistentn´ıho pole obsahuj´ıc´ı vektory ke tˇr´ıdˇen´ı a nˇekolika zadan ´ych parametr ˚u, jako je poˇcet vektor ˚u, jejich dimenze, typ tˇr´ıdˇen´eho prvku a velikost bloku perzistentn´ıho pole, je nutno pˇredat tˇr´ıdˇe SortArray tak´e instanci po-tomka tˇr´ıdy cSizeInfo obsahuj´ıc´ı informace potˇrebn´e k v ´ypoˇctu m´ısta podle zadan´eh ´ych parametr ˚u a hlaviˇcku vytvoˇren´eho perzistentn´ıho pole.

Nyn´ı si pop´ıˇseme nˇekter´e d ˚uleˇzit´e metody tˇr´ıdy ArrayTest. Vˇsechny metody jsou pops´any vygenerovanou program´atorskou dokumentac´ı na pˇriloˇzen´em CD.

6.1.1 Generov ´an´ı n ´ahodn ´ych dat

Metoda ArrayTest::Generate(cDataType *typ prvku, char *input file) je urˇcen´a ke generov´an´ı n´ahodn ´ych vektor ˚u, tedy vektor ˚u, kter´e maj´ı n´ahodnou dimenzi od 1 do zadan´e ma-xim´aln´ı dimenze a jejich prvky jsou n´ahodnˇe vygenerovan´e od 0 do hodnoty glob´aln´ı konstanty MAX GEN, nastaven´e standardnˇe na 1000. Poˇcet vektor ˚u a jejich maxim´aln´ı dimenzi urˇcuj´ı glob´aln´ı promˇenn´e count a dim. V t´eto metodˇe se tak´e vytv´aˇr´ı hlaviˇcka perzistentn´ıho pole, kter´a bude pouˇzita jako parametr tˇr´ıdy pro tˇr´ıdˇen´ı prvk ˚u.

Metoda m´a dva argumenty:

• prvn´ım je typ prvku, kter ´y bude pˇredstavovat jednotliv ´y prvek vektoru, jde o no-vou instanci potomka tˇr´ıdy cBasicType.

• t´ım druh ´ym je n´azev souboru perzistentn´ıho pole, kter ´y se vytvoˇr´ı touto metodou. Vkl´ad´an´ı n´ahodn ´ych dat prob´ıh´a vˇzdy pro jeden prvek, ten je uloˇzen do struktury per-zistentn´ıho pole a pot´e vypr´azdnˇen a t´ım pˇripraven pro dalˇs´ı plnˇen´ı.

(42)

34

6.1.2 Na ˇcten´ı dat z textov ´eho souboru

Metoda ArrayTest::GenerateFromTextFile(char *soubor, char *vstupni soubor) prov´ad´ı naˇc´ıt´an´ı vektor ˚u uloˇzen ´ych v textov´em souboru do perzistentn´ıho pole. Nejprve jsou z prvn´ıho ˇr´adku textov´eho souboru naˇcteny ´udaje o konkr´etn´ım typu tˇr´ıdˇen ´ych vektor ˚u, opˇet jde o jednoho z potomk ˚u tˇr´ıdy cBasicType, d´ale o maxim´aln´ı dimenzi vektor ˚u a nakonec o jejich celkov´em poˇctu. Pot´e je podle naˇcten´eho typu zavol´ana pˇretypovan´a metoda ArrayTest::LoadFromText(), kter´a zajist´ı spr´avn´e naˇcten´ı zbyl ´ych vektor ˚u do struktury per-zistentn´ıho pole.

Metoda vyˇzaduje dva argumenty:

• prvn´ı pˇredstavuje n´azev vstupn´ıho textov´eho souboru.

• druh ´y je vygenerovan ´y soubor struktury perzistentn´ıho pole, tedy vstupn´ı soubor pro tˇr´ıd´ıc´ı algoritmus.

6.2 Sablona RunInfoˇ

Jak jsme jiˇz popsali v kapitole Anal ´yza a n´avrh, ˇsablona RunInfo slouˇz´ı k ukl´ad´an´ı in-formac´ı o jednotliv ´ych skupin´ach vznikaj´ıc´ıch v prvn´ı ˇc´asti tˇr´ıd´ıc´ıho algoritmu. ˇSablona je parametrizov´ana konkr´etn´ım typem tˇr´ıdˇen´eho prvku a je poˇc´ıt´ano, ˇze jedna instance bude pˇredstavovat popis jedn´e skupiny. Lok´aln´ı promˇenn´e index a position zaznamen´avaj´ı index a pozici posledn´ıho vloˇzen´eho prvku, logick´a hodnota used urˇcuje, zda jiˇz byla tato skupina pouˇzita ve druh´e ˇc´asti tˇr´ıd´ıc´ıho algoritmu a max a min pˇredstavuj´ıc´ı maxim´aln´ı a minim´aln´ı prvek skupiny (tyto ´udaje se ukl´adaj´ı kv ˚uli pozdˇejˇs´ı optimalizaci). Pˇr´ıstup k tˇemto promˇenn ´ym je zapouzdˇren do metod Set a Get, maj´ıc´ıch standardn´ı konvenci, tedy napˇr. SetIndex() a GetIndex(). Pro jednoduˇsˇs´ı kop´ırov´an´ı cel ´ych ˇsablon je zde implemen-tov´an tak´e oper´ator rovn´a se.

6.3 Sablona SortArrayˇ

Nyn´ı se koneˇcnˇe dost´av´ame k ˇsablonˇe, ˇreˇs´ıc´ı poˇzadovan´e tˇr´ıdˇen´ı prvk ˚u na extern´ım ´uloˇziˇsti. Tato ˇsablona se, obdobnˇe jako ˇsablona RunInfo, parametrizuje konkr´etn´ım ty-pem tˇr´ıdˇen´eho prvku. Z veˇrejn ´ych metod obsahuje kromˇe konstruktoru metodu Sort(), jej´ıˇz zavol´an´ım dojde k postupn´emu spuˇstˇen´ı prvn´ı a druh´e ˇc´asti vnˇejˇs´ıho tˇr´ıd´ıc´ıho algo-ritmu.

Obˇe tyto ˇc´asti si podrobnˇe pop´ıˇseme.

6.3.1 Algoritmus pro vytvoˇren´ı setˇr´ıd ˇen ´ych skupin

Metoda pro vytvoˇren´ı setˇr´ıdˇen ´ych skupin implementovan´a podle algoritmu naˇcti-setˇr´ıd’-uloˇz popsan´eho v kapitole 3.2.1 se jmenuje SortArray<TupleType>::MakeRuns( cPersisten-tArrayHeader VarLen<TupleType> *mHeader, unsigned int ram size, unsigned int count). Jej´ı argumenty jsou:

(43)

• hlaviˇcka perzistentn´ıho pole, kterou jsme dˇr´ıve vytvoˇrili, zde se pˇred´av´a hlaviˇcka z testovac´ı tˇr´ıdy ArrayTest.

• velikost dostupn´e hlavn´ı pamˇeti pro algoritmus, je definovan´a poˇctem voln ´ych blok ˚u, kde jeden blok hlavn´ı pamˇeti odpov´ıd´a velikosti jednomu bloku perzis-tentn´ıho pole. Je stejn´a pro prvn´ı i druhou f´azi algoritmu. V t´eto f´azi velikost do-stupn´e hlavn´ı pamˇeti urˇcuje velikost jednotliv ´ych setˇr´ıdˇen ´ych skupin.

• posledn´ı poloˇzkou je poˇcet vektor ˚u, kter´e vstupn´ı perzistentn´ı pole obsahuje. Metoda vrac´ı logickou 1, pokud algoritmus probˇehne korektnˇe a v jeho pr ˚ubˇehu ne-dojde k ˇz´adn´e chybˇe, logickou nulu, pokud tomu tak nen´ı.

6.3.2 Algoritmus pro sl ´ev ´an´ı setˇr´ıd ˇen ´ych skupin

Metoda zajiˇst’uj´ıc´ı sl´ev´an´ı setˇr´ıdˇen ´ych skupin implementovan´a podle algoritmu vyuˇz´ıvaj´ıc´ıho k-cestn ´y mergesort, popsan ´y v kapitole 3.2, m´a n´azev

SortArray<TupleType>::Merge( unsigned int ram size, char *vystupni soubor, bool use optimalization) a n´asleduj´ıc´ı argumenty:

• velikost dostupn´e hlavn´ı pamˇeti pro algoritmus, je definovan´a poˇctem voln ´ych blok ˚u, kde jeden blok hlavn´ı pamˇeti odpov´ıd´a velikosti jednomu bloku perzis-tentn´ıho pole. Je stejn´a pro prvn´ı i druhou f´azi algoritmu. V t´eto f´azi velikost do-stupn´e hlavn´ı pamˇeti urˇcuje poˇcet najednou otevˇren ´ych skupin pro sl´ev´an´ı.

• dalˇs´ım parametrem je jm´eno v ´ystupn´ıho souboru, jde o v ´ysledn ´y soubor obsahuj´ıc´ı setˇr´ıdˇen´e perzistentn´ı pole.

• posledn´ım parametrem je logick´a hodnota urˇcuj´ıc´ı, zd´a m´a algoritmus vyuˇz´ıvat implementovanou optimalizaci.

Metoda vrac´ı, stejnˇe jako metoda implementuj´ıc´ı prvn´ı ˇc´ast tˇr´ıd´ıc´ıho algoritmu, logic-kou 1, pokud algoritmus probˇehne korektnˇe a v jeho pr ˚ubˇehu nedojde k ˇz´adn´e chybˇe, logickou nulu, pokud tomu tak nen´ı.

Mimo algoritm ˚u pro samotn´e tˇr´ıdˇen´ı je zde i nˇekolik pomocn ´ych metod, at’ uˇz jde o metodu Quicksort(), vyuˇz´ıvanou pˇri tˇr´ıdˇen´ı ˇc´asti prvk ˚u v hlavn´ı pamˇeti potˇrebnou v prvn´ı f´azi tˇr´ıd´ıc´ıho algoritmu, nebo metodu Zformuj pole bin(), kter´a novˇe vloˇzen ´y prvek do pole index ˚u skupin bin´arnˇe zaˇrad´ı podle jeho velikosti na patˇriˇcn´e m´ısto v poli.

6.3.3 Optimalizace algoritmu pro sl ´ev ´an´ı setˇr´ıd ˇen ´ych skupin

Optimalizace implementov´ana ve druh´e ˇc´asti algoritmu pro tˇr´ıdˇen´ı na extern´ım ´uloˇziˇsti vyuˇz´ıv´a prognostickou metodu, konkr´etnˇe upravenou posloupnost spotˇreby, popsanou v kapitole 3.3.

Pˇri sl´ev´an´ı m´ame k dispozici pouze N stran voln´e hlavn´ı pamˇeti, znamen´a to, ˇze m ˚uˇzeme najednou otevˇr´ıt a sl´evat jen N skupin. Pokud se jedna ze vkl´adan ´ych skupin vypr´azdn´ı, hled´ame na jej´ı m´ısto jinou vyhovuj´ıc´ı skupinu. Nejprve z jeˇstˇe nesl´evan ´ych

(44)

36

Algoritmus 4: Pseudok ´od algoritmu naˇcti-setˇr´ıd’-uloˇz

Input: hlaviˇcka vstupn´ıho pole, velikost pamˇeti, poˇcet vektor ˚u vytvoˇr a inializuj potˇrebn´e promˇenn´e;

vstupn´ı soubor.otevˇri();

kontext.otevˇri(vstupn´ı soubor.zaˇc´atek()); v ´ystupn´ı soubor.vytvoˇr();

poˇcet prvk ˚u ve skupinˇe := (ram size * block size) / (dim * sizeof(typ)); poˇcet skupin := poˇcet vektor ˚u / poˇcet prvk ˚u ve skupinˇe;

if (poˇcet vektor ˚u % ((int)(ram size * block size) / (dim * sizeof(typ))) != 0) then

poˇcet skupin++;

vytvoˇr a inicializuj In desc[poˇcet skupin+1]; //popisovaˇc skupin

inicializuj pole[poˇcet prvk ˚u ve skupinˇe];

//pole pˇredstavuj´ıc´ı data z perzistentn´ıho pole v hlavn´ı pamˇeti i:=0;

p i:=0;

for do

pole[i++] = kontext.vrat’Prvek();

if kontext != vstupn´ı soubor.konec then if i == poˇcet prvk ˚u ve skupinˇe then

Quicksort(pole, 0, i);

for x:=0 to i do

v ´ystupn´ı soubor.pˇridej(pole[x]); Uloˇz informace o skupinˇe do In desc[p i]; i:=0; p i++; else Quicksort(pole, 0, i); for x:=0 to i do v ´ystupn´ı soubor.pˇridej(pole[x]); Uloˇz informace o skupinˇe do In desc[p i]; break;

kontext.zavˇri();

vstupn´ı soubor.zavˇri(); v ´ystupn´ı soubor.zavˇri(); smaˇz jiˇz nepotˇrebn´e objekty;

(45)

Algoritmus 5: Pseudok ´od k-cestn´eho sl´ev´an´ı bez rekurze

Input: velikost pamˇeti, v ´ystupn´ı soubor vytvoˇr a inializuj potˇrebn´e promˇenn´e; Out poˇcet skupin := 0;

for do

vytvoˇr a inicializuj Out desc[poˇcet skupin]; vstup.otevˇri();

v ´ystup.vytvoˇr();

vytvoˇr a inicializuj pole kontext ˚u[poˇcet skupin+1]; i := 0;

dolni := 0; horni := 0;

Out poˇcet skupin := 0;

max = (velikost pamˇeti > poˇcet skupin)?poˇcet skupin:velikost pamˇeti;

repeat

vektor<unsigned int> pole sk;

for i:=dolni to horni do

inicializuj kontext In pole ctx[i];

In pole ctx[i].otevˇriKontext(zaˇc´atek it´e skupiny); pole sk.dejNaKonec(i);

In desc[i].NastavPouˇzit´ı(true);

if pole sk.velikost() == max then

break;

vyvtoˇr a inicializuj pole index ˚u skupin; dolni := pole sk[0];

horni := pole sk[pole sk.velikost()-1]; horni++;

setˇrid’ pole index ˚u skupin podle nejmenˇs´ıho prvku In pole ctx; Sl´evej skupiny();

uloˇz informace o v ´ysledn´e skupinˇe do Out desc[Out poˇcet skupin]; dolni := horni;

until horni != poˇcet skupin; vstup.zavˇri();

v ´ystup.zavˇri(); celk poˇcet++;

poˇcet skupin := Out poˇcet skupin; In desc = Out desc;

if Out poˇcet skupin == 1 then

break;

je-li posledn´ım v ´yst. souborem soubor doˇcasn ´y, naˇcti jej do souboru v ´yst.; smaˇz jiˇz nepotˇrebn´e objekty;

(46)

38

Algoritmus 6: Pseudok ´od metody Sl´evej() potˇrebn´e k algoritmu k-cestn´eho sl´ev´an´ı bez rekurze

Input: Pole index ˚u skupin, In pole ctx, In desc, vstupn´ı a v ´ystupn´ı perz. pole mnoˇzstv´ı opakov´an´ı = 0;

poˇcet sk = pole sk.velikost();

for do

if je-li prvek ze skupiny uloˇzen´e na nult´em indexu v poli pole index ˚u skupin > neˇz

prvek ze skupiny uloˇzen´e na dalˇs´ım indexu then

bin´arnˇe zatˇrid’ prvek na nult´em indexu v poli pole index ˚u skupin pomoc´ı kontextu In pole ctx;

v ´ystup.pˇridej(prvek odpov´ıdaj´ıc´ı In pole ctx[pole index ˚u skupin[0]]);

if jde-li o prvn´ı prvek vloˇzen´y do skupiny then

uloˇz jej jako minimum;

if nen´ı-li pr´azdn´a skupina, ze kter´e byl vloˇzen posledn´ı prvek then

posu ˇn kontext In pole ctx[pole index ˚u skupin[0]];

else

if m´a-li b´yt pouˇzita optimalizace then

Optimalizuj();

if byla nalezena optimalizace then

pokraˇcuj ve sl´ev´an´ı;

else

uloˇz posledn´ı prvek jako maximum skupiny; zavˇri kontext In pole ctx[pole index ˚u skupin[0]]; odeber ukonˇcenou skupinu z pole index ˚u skupin; poˇcet sk–;

if poˇcet sk == 0 then

break;

(47)

skupin vybereme ty, kter´e maj´ı minimum vˇetˇs´ı nebo rovno naposledy vloˇzen´emu prvku, logicky n´as zaj´ımaj´ı jen skupiny, kter´e m´a cenu v aktu´aln´ım bodˇe d´ale sl´evat. Z tˇechto skupin pak vyberemu tu, jej´ıˇz maximum m´a nejmenˇs´ı hodnotu.

Tento postup m ˚uˇze uˇsetˇr´ıt nˇekolik pr ˚uchod ˚u v druh´e ˇc´asti algoritmu, v ide´aln´ım pˇr´ıpadˇe by sl´ev´an´ı probˇehlo jen v jednom pr ˚uchodu, v nejhorˇs´ım algoritmus probˇehne stejnˇe rychle, jako bez optimalizace.

Algoritmus 7: Pseudok ´od upraven´e posloupnosti spotˇreby

ve chv´ıli, kdy dojde k vypr´azdnˇen´ı jedn´e ze vstupn´ıch skupin ve druh´e ˇc´asti algoritmu prov´adˇej:

ind dalˇs´ıho := -1;

for pp:=horni to poˇcet skupin do

if !In desc[pp].BylaPouˇzita() and In desc[pp].Minimum() >= posledn´ı vloˇzen´y prvek then

if pp == -1 then

maximum := In desc[pp].Maximum(); ind dalˇs´ıho := pp;

else if In desc[pp].Maximum() < maximum then

ind dalˇs´ıho := pp;

if ind dalˇs´ıho != -1 then

naˇcti na pozici posledn´ı vypr´azdnˇen´e skupiny skupinu s indexem ind dalˇs´ıho; vytvoˇr a otevˇri pro ni kontext;

In desc[ind dalˇs´ıho].BylaPouˇzita(true);

6.4 Pouˇzit ´e technologie a programov ´e vybaven´ı

• Pro v ´yvoj komponenty pouˇz´ıv´am Visual Studio ve verzi 2008 od spoleˇcnosti Micro-soft. Jde o integrovan´e v ´yvojov´e prostˇred´ı pro v ´yvoj aplikac´ı s podporou nˇekolika programovac´ıch jazyk ˚u, obsahuje propracovan ´y editor k ´odu podporuj´ıc´ı Intelli-Sense a refaktoring, v ´ykonn ´y debugger, grafick ´y editor webov ´ych str´anek, atd. • Pro modelov´an´ı syst´emu pomoc´ı jazyka UML vyuˇz´ıv´am n´astroje Enterprise

Archi-tect od spoleˇcnosti Sparx Systems ve verzi 7.

• Aplikace byla vyv´ıjena a testov´ana na operaˇcn´ım syst´emu Windows XP s bal´ıkem SP3 spoleˇcnosti Microsoft.

(48)

Figure

Updating...

References

Updating...

Related subjects :