tiesiniŲ lygČiŲ sistemŲ sprendimo
TRANSCRIPT
VILNIAUS PEDAGOGINIS UNIVERSITETAS
MATEMATIKOS IR INFORMATIKOS FAKULTETAS
INFORMACINIŲ TECHNOLOGIJŲ KATEDRA
ALINA ANISIMOVA
TIESINIŲ LYGČIŲ SISTEMŲ SPRENDIMO
LYGIAGRETŪS ALGORITMAI
Magistro baigiamasis darbas
Darbo vadovas doc. dr. Tomas Petkus
Vilnius, 2011
2
TURINYS
ĮVADAS .................................................................................................................................................. 3
1. LYGIAGRETIEJI SKAIČIAVIMAI........................................................................................... 5
1.1. Lygiagrečiųjų algoritmų svarbiausi ypatumai .................................................................... 5
1.2. Lygiagrečiųjų algoritmų vertinimo kriterijai...................................................................... 7
1.3. Duomenų persiuntimo kaštų teorinis modelis ..................................................................... 8
1.4. Programinė įranga ................................................................................................................. 9
1.4.1. MPI apžvalga ................................................................................................................. 10 1.4.2. Šešios svarbiausios MPI funkcijos................................................................................. 10
2. TIESINIŲ LYGČIŲ SISTEMŲ SPRENDIMO METODAI.................................................... 14
2.1. Tiesinių lygčių sistemų apžvalga......................................................................................... 14
2.2. Tiesiniai metodai .................................................................................................................. 15
2.2.1. Gauso metodas ............................................................................................................... 16 2.2.2. Gauso ir Žordano metodas ............................................................................................. 18 2.2.3. Kramerio formulės ......................................................................................................... 19 2.2.4. Atvirkštinės matricos metodas ....................................................................................... 20 2.2.5. Tiesinių homogeninių lygčių sistemos sprendimas........................................................ 20
2.3. Iteraciniai metodai ............................................................................................................... 20
2.3.1. Paprastų iteracijų metodas.............................................................................................. 21 2.3.2. Iteracinis Jakobio metodas ............................................................................................. 21 2.3.3. Zeidelio metodas ............................................................................................................ 23
3. EKSPERIMENTINIS TYRIMAS .............................................................................................. 25
3.1. Lygiagretusis Jakobio iteracinio metodo algoritmas ........................................................ 25
3.2. Lygiagretieji Gauso metodo algoritmai ............................................................................. 28
3.2.1. Lygiagretusis blokinio duomenų paskirstymo Gauso metodo algoritmas ..................... 29 3.2.2. Lygiagretusis ciklinio duomenų paskirstymo Gauso metodo algoritmas ...................... 31
3.3. Algoritmų efektyvumo analizė ............................................................................................ 34
3.3.1. Lygiagretusis Jakobio iteracinio metodo algoritmas...................................................... 34 3.3.2. Lygiagretusis blokinio duomenų paskirstymo Gauso metodo algoritmas ..................... 37 3.3.3. Lygiagretusis ciklinio duomenų paskirstymo Gauso metodo algoritmas ...................... 40 3.3.4. Rezultatų, gautų eksperimentų metu, vertinimas ........................................................... 42
4. IŠVADOS...................................................................................................................................... 45
5. SANTRAUKA .............................................................................................................................. 47
6. SUMMARY .................................................................................................................................. 47
7. LITERATŪRA ............................................................................................................................. 48
8. PRIEDAS ...................................................................................................................................... 49
3
ĮVADAS
Vis dažniau atsiranda poreikis spręsti labai didelius uždavinius. Galima pateikti tokias sritis kaip
statistika, inžinerija, matematika, gamtų mokslai, meteorologija ir t.t. Vienas pagrindinių uždavinių
sprendimo reikalavimų yra būtinybė minimizuoti laiką. Todėl kasdien vis ieškoma efektyvesnių ir
greitesnių sprendimo būdų. Tobulėjant technologijoms tai tampa daug paprasčiau. Šiandien
kompiuteris sprendžia be galo daug įvairių, sudėtingų uždavinių, tačiau kartais pasitelkdami ir net
pačius greičiausius šiuolaikinius kompiuterius negalime laiku rasti atsakymo. Kitų uždavinių
sprendimą ribojančiu veiksniu gali tapti vieno kompiuterio atminties resursai. Tokiais atvejais padeda
lygiagretieji kompiuteriai. Toks rastas sprendimas padėjo išspręsti daugelį problemų, tokių kaip
atminties resursų stoka, sprendimo radimo laiko sumažėjimas, finansinių investicijų mažinimas.
Trumpai tariant kompiuterių sujungimas tinklu į vieną virtualių kompiuterių klasterį pakeitė
daugeliuose sričių superkompiuterius, taip naudojant visus galimus resursus ir taupant papildomus
finansus. Be to į klasterį gali būti apjungti kaip ir du taip ir daugiau skirtingų kompiuterių, pavyzdžiui
Google apjungė daugiau kaip 8000 kompiuterių. Vienas iš pirmiausių projektų, kuris apjungė
kompiuterius į vieną klasterį spręsti vienos užduoties, buvo Beowulf centre Nasa Goddard Space
Flight Center, kuris startavo 1994 metais. Buvo sukurtas 16-procesorinis klasteris, kuris turėjo
atlikinėti skaičiavimus reikalingus projektui Earth and Space Sciences. Projektas Beowulf buvo geru
postūmiu lygiagrečiųjų skaičiavimų vystimuisi [14]
Nuo 1993 metų superkompiuterius pradėta sistemingai lyginti pagal kelis testus. Vienas iš
populiariausių yra Linpack testas; jame sprendžiamos tiesinių lygčių sistemos su labai didelėmis
matricomis. 500 greičiausių kompiuterių sąrašą galime surasti internete http://www.top500.org. Įdomu
pastebėti, jog aštuoniasdešimt ketvirtasis greičiausias pasaulio kompiuteris yra virtualusis kompiuterių
klasteris, sudarytas iš 580 standartinių darbo stočių. Jis kainuoja tik 5 milijonus dolerių, tai yra
maždaug dešimt kartų mažiau už tokio paties greitaeigiškumo superkompiuterį. Tarp 500 greičiausių
kompiuterių yra dar trys kompiuterių klasteriai [1].
Tokių kompiuterių klasterių poreikis vis auga. Kuriamos tokios kompiuterių sistemos, kuriose
efektyviai galima naudoti vis daugiau procesorių bei didesnius atminties resursus. Atsiranda poreikis
tobulinti ir programinę įrangą. Yra sukurta daug programavimo kalbų ir įrankių, skirtų nuosekliems
kompiuteriams. Ši patirtis yra svarbi ir naudojant lygiagrečiuosius algoritmus. Tačiau lygiagretieji
skaičiavimai suformuluoja daug naujų reikalavimų. Šiuo metu sukurta daug lygiagrečiojo
programavimo standartų, kurie skirti populiariausiems lygiagrečiųjų kompiuterių architektūros tipams.
Nagrinėdami įvairių uždavinių sprendimo algoritmus, pastebime, kad daugelio iš jų realizavimas
yra susietas su tiesinės algebros uždavinių sprendimu. Kitą didelę uždavinių grupę sudaro
matematiniai modeliai, kurie aprašomi diferencialinių lygčių sistemomis. Todėl kuriamos paprogramių
4
bibliotekos, kuriuose surinkti efektyviausi tokių uždavinių sprendimo algoritmai. Tokie darbai
atliekami ir lygiagrečiųjų algoritmų srityje [1].
Šiame darbe apžvelgsime vieną pagrindinių tiesinės algebros uždavinių – tiesinių lygčių sistemų
sprendimai. Aptarsime tiesinių lygčių sistemų sprendimo metodus bei jų lygiagrečius algoritmus.
Darbo tikslas:
Tiesinių lygčių sistemų lygiagrečių sprendimo metodų tyrimas
Darbo uždaviniai:
- Apžvelgti tiesinių lygčių sistemų sprendimo būdus.
- Išanalizuoti tiesinių lygčių sistemų sprendimo metodų lygiagrečius algoritmus.
- Parinkus keletą metodų atlikti eksperimentus kompiuterių tinkle.
- Atlikti eksperimentus pasirinktiems lygiagretiems algoritmams su skirtingais procesorių
ir procesų kiekiais.
- Atlikti rezultatų analizę.
5
1. LYGIAGRETIEJI SKAIČIAVIMAI
Didėjant kompiuterių spartai ir jų atminties galimybėms, matomas spartus naujos technologijos –
skaičiavimo eksperimento plitimas. Daugelyje taikymo sričių, tokių kaip lėktuvų ir automobilių
pramonė, chemijos ir biochemijos technologijos, genų inžinerija, oro ir dirvos užterštumo tyrimai,
kompiuterinė grafika, kompiuterinė tomografija, fiziniai eksperimentai yra keičiami virtualiuoju
kompiuteriniu modeliavimu. Tokiais eksperimentais atliekamų skaičiavimų apimtys yra labai didelės,
be to, dažnai reikia tenkinti papildomą sąlygą, kad atsakymą reikia gauti ne vėliau už nustatytą laiko
momentą. Pavyzdžiui, tokia sąlyga yra esminė, kai sprendžiame oro prognozės uždavinį. Net ir labai
tiksli rytdienos oro prognozė yra niekam neįdomi, jei ją sužinome po dviejų parų [1].
1.1. Lygiagrečiųjų algoritmų svarbiausi ypatumai
Lygiagretieji skaičiavimai yra naudojami dviem tikslams: duotuosius uždavinius išspręsti kuo
greičiau ir išspręsti sudėtingesnius uždavinius, nei tai galima padaryti naudojant tik nuoseklų
algoritmą.
Nuoseklieji skaičiavimai (žr. 1.1 pav.) (angl. serial computing) užduoties problemą išskaido į
diskrečią instrukcijų seką, kurios yra vykdomos viena po kitos (nuosekliai). Bet kuriuo laiko momentu
gali būti vykdoma tik viena instrukcija.
1.1 pav. Nuoseklieji skaičiavimai
Skirtingai nuo nuosekliųjų skaičiavimų lygiagretieji skaičiavimai (žr. 1.2 pav.) vykdomi
naudojant keletą procesorių vienu metu. Užduoties problema yra išskaidoma į atskiras dalis, kurios
gali būti sprendžiamos lygiagrečiai. Kiekviena atskira dalis yra skaičiuojama nuosekliai, tačiau
skirtingų dalių instrukcijos yra vykdomos skirtinguose procesoriuose tuo pačiu metu.[12]
6
1.2 pav. Lygiagretieji skaičiavimai[12]
Lygiagretus duomenų apdorojimas turi dvi atmainas: lygiagretų ir konvejerinį variantą.
Konvejerinis apdorojimas. Konvejerinio apdorojimo būdu visos bendros operacijos yra
išskaidomos į kelis vienodos trukmės etapus. Kiekvienas etapas perduoda savo rezultatą kitam etapui ir
tuo pat laiku priima naujus duomenis. Jeigu konvejerinis įrenginys turi l etapų, o kiekvienas etapas
atliekamas per vieną laiko vienetą, tai n nepriklausomų operacijų apdorojimas tokiu įrenginiu sudarys
l+n-1 laiko vienetų.
Lygiagretus apdorojimas. Jeigu įrenginys atlieka vieną operaciją per tam tikrą laiko vienetą, tai
1000 operacijų jis atliks per 1000 laiko vienetų. Padarius prielaidą, kad turime penkis tokius pačius
nepriklausomus įrenginius, galinčius vienu metu ir nepriklausomai vienas nuo kito veikti, tai 1000
operacijų penkių įrenginių sistema gali atlikti jau ne per 1000, o per 200 laiko vienetų. Analogiškai N
įrenginių sistema tą patį darbą idealiu atveju atliks per 1000/N laiko vienetų.[3]
Lygiagrečiųjų algoritmo pranašumas yra akivaizdus. Kyla klausimas apie jų sudarymą. Sudarant
bet kokį lygiagretųjį algoritmą, reikia išspręsti tris uždavinius. Pirma, reikia sudaryti užduočių, kurias
galima vykdyti lygiagrečiai, sąrašą. Antra, reikia nurodyti jų vykdymo tvarką. Trečia, reikia sudaryti
uždavinio sprendimo tvarkaraštį, t.y. paskirstyti uždavinius procesoriams. Sprendžiant šiuos
uždavinius, siekiama minimizuoti algoritmo realizacijos laiką. Ypač aktualus yra užduočių
paskirstymas tarp procesorių uždavinys, kurį tenka spręsti kuriant bet kokį lygiagretųjį algoritmą.
Užduočių paskirstymas procesoriams gali būti atliekamas dviem būdais.
Pirmasis būdas – statiškas paskirstymas skaičiavimo pradžioje, naudojantis informaciją apie
užduočių sudėtingumą ir procesorių greitaeigiškumą.
Antrasis būdas – dinamiškas darbo paskirstymas skaičiavimo eigoje naudojamas tada, kai
užduočių sudėtingumas yra kintamas ar neprognozuojamas ir procesorių greitaeigiškumas gali keistis
skaičiavimo metu. Tokiuose algoritmuose realizuojamas darbo perskirstymo mechanizmas.
7
Pagal sprendžiamus uždavinius lygiagretieji algoritmai skirstomi į kelias klases: duomenų
lygiagretumo algoritmus, funkcinio lygiagretumo algoritmus, šeimininkas - darbininkai tipo
algoritmus [1], [13] .
1.2. Lygiagrečiųjų algoritmų vertinimo kriterijai
Pirmasis kriterijus, kuriuo galima palyginti kelis lygiagrečiuosius algoritmus, yra lygiagrečiojo
algoritmo pagreitėjimas (žr. 1.2.1 formulę) [1], sprendžiant uždavinį su p procesorių: *
1 ;pp
TS
T=
Čia: T *1 – laikas, per kurį uždavinys išsprendžiamas geriausiu žinomu nuosekliuoju algoritmu;
T p – laikas, kurį sugaišta lygiagretusis algoritmas, spręsdamas uždavinį su p procesorių.
Pažymėsime, kad T *1 ir T1 dažniausiai skiriasi, nes net tais atvejais, kai lygiagretusis algoritmas
yra sudarytas modifikuojant nuoseklųjį, atsiranda papildomos programinės konstrukcijos, lėtinančios
algoritmą, todėl visuomet yra teisinga nelygybė TT 1*1 £ . Taip pat galima pastebėti, jog skirtingi
lygiagretieji algoritmai, sprendžiantys tą patį uždavinį skirtingais būdais, gali būti pranašesni esant tam
tikram procesorių skaičiui ir prastesni esant kitam procesorių kiekiui. Visa tai gali priklausyti nuo
lygiagrečiojo kompiuterio.
Kitas kriterijus, kuriuo galima vertinti lygiagretųjį algoritmą, yra procesorių panaudojimo
efektyvumas (žr. 1.2.2 formulę) [1]:
;pp
SE
p=
Čia: Ep – procesorių panaudojimo efektyvumas;
Sp – spartinimo koeficientas;
p – procesorių skaičius.
Efektyvumas parodo, kaip naudojami procesoriai. Sprendžiant kai kuriuos uždavinius, didelis
efektyvumas gali būti pasiektas tik esant fiksuotam procesorių kiekiui, tačiau toliau jam didėjant,
efektyvumas mažėja. Efektyvumas priklauso ne tik nuo uždavinio, bet ir nuo lygiagrečiojo algoritmo
bei lygiagrečiųjų kompiuterių parametrų: granuliacijos, procesorių skaičiavimo greičio, komunikacijos
greičių ir pan. To paties algoritmo efektyvumas skirtinguose kompiuteriuose gali labai skirtis.
Paprastai, kuo didesnis procesorių komunikacijos greitis ir kuo lėtesni procesoriai, tuo geresnis
efektyvumas yra pasiekiamas. Daugiaprocesoriniuose superkompiuteriuose santykis tarp procesorių
greičio ir komunikacijos greičio yra artimas vienetui, todėl lygiagrečiojo algoritmo efektyvumą
(1.2.1)
(1.2.2)
8
daugiausia lemia to algoritmo savybės. Amdalo (angl. Amdahl) dėsnis [1] teigia, kad bet kurio
lygiagrečiojo algoritmo efektyvumas yra mažesnis už vienetą ir didėjant procesorių skaičiui jis mažėja.
1.3. Duomenų persiuntimo kaštų teorinis modelis
Lygiagrečiųjų algoritmų realizavimo metu procesoriai turi keistis informacija. Duomenų
persiuntimo trukmė labai priklauso nuo lygiagrečiojo kompiuterio tipo ir tinklo topologijos.
Bendrosios atminties lygiagrečiuose kompiuteriuose kiekvienas procesorius tiesiogiai gali perskaityti
bet kurio kintamojo reikšmę arba užrašyti naują jo reikšmę. Tačiau reikia atsižvelgti į šių kompiuterių
atminties hierarchiją: kiekvienam procesoriui kai kurie duomenys yra pasiekiami greičiau negu kiti.
Paskirstytosios atminties lygiagrečiuose kompiuteriuose procesoriai keičiasi duomenimis siųsdami
pranešimus.
Tarkime, kad pranešimą sudaro n skaičių. Tada pakankamai tiksliai vieno pranešimo persiuntimo
kaštus galime įvertinti formule [1]
t na b= +
Čia: β – vieno skaičiaus siuntimo laikas, atvirkštinis dydis 1/β yra vadinamas duomenų
perdavimo linijos pločiu.
Paaiškinsime parametro α fizinę prigimtį. Prieš išsiųsdamas pranešimą siuntėjas pagal tam tikrus
reikalavimus parengia pranešimo turinį, prideda papildomus pranešimo atributus, susisiekia su
procesu, atsakingu už duomenų persiuntimą kompiuterio tinkle, nustato optimalų maršrutą. Šie kaštai
žymimi ts ir vadinami pranešimo parengimo laiku. Išsiuntus pranešimą, turi praeiti tam tikras laikas,
kol informacija apie pranešimą pasiekia adresatą, ir jis nusprendžia, kur dėti pranešimą, arba
persiunčia jį kitam procesui; šis laikas žymimas th ir vadinamas pranešimo judėjimo laiku. Tada α
įvertina suminį šių kaštų dydį [1]
s ht ta = +
Šis dydis vadinamas starto laiku. Vėliau pranešimo persiuntimo greitis priklauso tik nuo to, koks
yra perdavimo linijos plotis. Čia galima pasitelkti analogiją su žygiuojančių kareivių būriu – tada α yra
laiko tarpas, per kurį paskirties vietą pasieks kolonos pirmoji kareivių greta, vėliau žygį baigusių
kareivių skaičius priklauso tik nuo kolonos pločio ir eilių tankio.
Visuose lygiagrečiuose kompiuteriuose pradinė pranešimo perdavimo stadija yra daug ilgesnė už
vieno skaičiaus persiuntimo laiką, α yra didesnis už β šimtus ar net tūkstančius kartų. Šis skirtumas
ypač didelis kompiuterių klasteriuose, sujungtuose vietiniu tinklu (angl. LAN – local area network).
(1.2.3)
(1.2.4)
9
Nors ir toks paprastas duomenų persiuntimo kaštų teorinis modelis yra naudingas kuriant
lygiagrečiuosius algoritmus. Pirmoji praktinė rekomendacija yra tokia: kelis trumpus pranešimus
tikslinga susieti į vieną pranešimą, taip sutaupomos pranešimo parengimo sąnaudos [1].
1.4. Programinė įranga
Kitas svarbus lygiagrečiųjų algoritmo sudarymo žingsnis – užrašyti šiuos algoritmus formalia
programavimo kalba ir atlikti skaičiavimus. Yra daug populiarių programavimo kalbų, kuriomis
užrašomi nuoseklūs algoritmai. Pirmiausia reikia nuspręsti, ar realizuojant lygiagrečiuosius algoritmus
kuriamos bus naujos programavimo kalbos, ar užteks papildyti jau egzistuojančias. Atsakant į šį
klausimą, reikia nustatyti, kokių papildomų priemonių reikia norint užrašyti lygiagretųjį algoritmą [1].
Čia verta paminėti kelis populiariausius standartus:
MPI – buvo suburta grupė specialistų, kuri sudarė paskirstytų skaičiavimų standartą ir
rekomendavo jį naudoti paskirstytos atminties lygiagrečiuosiuose kompiuteriuose. Šis standartas buvo
pavadintas MPI (angl. Message-Passing Interface). Jį sudarant buvo pasitelkta kitų programavimo
bibliotekų (PVM – Parallel Virtual Machine, Chameleon, PARMACS) ypatybės bei įvertinti naujausi
teoriniai siūlymai [1].
HPF – dar vienas standartas, praplečiantis Fortrano 90 galimybes ir leidžiantis efektyviai
realizuoti daugelį lygiagrečiųjų algoritmų. HPF leidžia išskirti lygiagrečiąsias algoritmo dalis
(duomenų lygiagretumo panaudojimas) ir paskirstyti duomenis procesoriams. Programuotojui nereikia
pačiam rūpintis duomenų perdavimo procesoriams procedūromis.
OpenMP – programavimo standartas, skirtas realizuoti lygiagretiesiems algoritmams bendros
atminties kompiuteriuose. Kadangi OpenMP skirtas bendros atminties kompiuteriams, programuotojui
nereikia rūpintis duomenų apsikeitimu tarp skirtingų procesorių. Algoritmas dalinamas į nuosekliąsias
ir lygiagrečiąsias dalis, kurios vykdomos procesų grupėse. Procesai naudoja bendrus ir lokalius
kintamuosius. Bendras kintamasis yra bendras visiems grupės procesams, o lokalus kintamasis
sukuriamas kiekviename procese. OpenMP lokalūs kintamieji yra analogiški HPF ir MPI procesų
kintamiesiems.
Parallel Virtual Machine (PVM) – programinės įrangos paketas, skirtas sujungti skirtingo tipo
kompiuterius į vieną lygiagretųjį kompiuterį. Taigi didelių skaičiavimų problemas galima efektyviai
išspręsti naudojant bendrą galią ir atmintį kelių kompiuterių.
Šiame darbe bus naudojamas populiariausias bei nemokamas taikomasis paketas MPICH v.1.2.5,
kuris įgyvendina MPI standartą [17].
10
1.4.1. MPI apžvalga
Paminėsime svarbiausias MPI standarto realizavimo ypatybes:
- MPI yra biblioteka, o ne nauja programavimo kalba. Ji tik apibrėžia paprogramių vardus,
parametrus ir jų funkcinę paskirtį. Šias paprogrames galima naudoti Fortan 77 ir C
kalbomis parašytose programose; parengtos Fortran 95 ir C++ versijos [1].
- MPI realizuotas išreikštinis duomenų siuntimo modelis. Apibrėžtos ne tik būtinosios
programavimo priemonės, be kurių negalime užrašyti lygiagrečiojo algoritmo,
realizuojamo paskirstytos atminties lygiagrečiuoju kompiuteriu, bet ir daug papildomų
paprogramių, lengvinančių algoritmo realizaciją arba padidinančių algoritmo efektyvumą.
MPI leidžia atlikti skaičiavimus su heterogeniškais kompiuteriais [1].
- MPI standartas apibrėžia tik funkcinę paprogramės paskirtį, bet nereglamentuoja jos
realizacijos, Todėl skirtingų tipų kompiuterių gamintojai gali šias paprogrames realizuoti
efektyviausiu šiam kompiuteriui būdu [1].
- MPI standartu parašyta programa be pakeitimų gali būti perkelta iš vieno tipo
kompiuterio į kito tipo kompiuterį. Tai ypač svarbu kuriant matematinių algoritmų
bibliotekas [1].
Svarbu paminėti, jog programinis paketas MPICH v.1.2.5 iš standarto MPI leidžia sujungti į
vieną serijinius, lygiagrečiuosius ir vektorinius kompiuterius, kuriuos galima įsivaizduoti kaip vieną
didelį virtualų kompiuterį su paskirstyta atmintimi, pavadintą virtualia mašina. Šis programinės
įrangos paketas pasižymi sugebėjimu automatiškai pradėti darbą virtualioje mašinoje, užtikrinti
komunikaciją tarp procesų ir sinchronizuoti darbą. Uždaviniai gali būti lygiagretinami naudojant
pranešimo siuntimo konstrukciją, kuri būdinga daugybei paskirstytos atminties kompiuterių. Tokiu
būdu, siunčiant ir gaunant pranešimus, galima lygiagrečiai spręsti uždavinius, nepaisant turimų
kompiuterių ir jų buvimo vietos. MPICH leidžia prijungti virtualią mašiną prie įvairiausių tinklų. Čia
galima naudoti kompiuterį, turintį daug procesų, galima naudoti lokalųjį arba globalųjį tinklus [13].
1.4.2. Šešios svarbiausios MPI funkcijos
Išsamų MPI standartą sudaro virš 200 pagrindinių paprogramių funkcijų. Be to, jau parengtas ir
MPI-2 praplėtimas. Tačiau daugelis šių paprogramių yra tik kelių pagrindinių funkcijų skirtingos
versijos, leidžiančios efektyviau realizuoti kai kuriuos algoritmus. Lygiagretaus algoritmo realizavimo
programa gali būti realizuota šešių pagrindinių funkcijų pagalba (žr. 1.1 lentelę) [1]:
11
Lentelė 1.1. Pagrindinės MPI funkcijos MPI funkcija Jos paskirtys
MPI_Init Sukuriamas virtualus lygiagretus kompiuteris
MPI_Comm_size Nustatoma, kiek procesų bus naudojama virtualiame kompiuteryje
MPI_Comm_rank Grąžina proceso numerį
MPI_Send Leidžia nusiųsti pranešimą
MPI_Recv Leidžia gauti pranešimą
MPI_Finalize Visus procesus informuoja, kad lygiagretus darbas baigėsi
Trumpai aptarsime kiekvieną iš šių funkcijų.
MPI_Init. (MPI_Init (int *argc, char ***argv)). Ši funkcija turi būti iškviesta kiekvienos MPI
programos pradžioje. Ji apibrėžia MPI aplinką, todėl MPI_Init galima kviesti tik vieną kartą.
MPI_Comm_size. (MPI_Comm_size (MPI_Comm comm, int *size)). Naudodami MPI
biblioteką, lygiagretųjį algoritmą skaidome į procesus, kurie gali būti vykdomi lygiagrečiai. Keli
procesai gali būti realizuoti tame pačiame procesoriuje, taigi procesų skaičius nebūtinai sutampa su
procesorių skaičiumi. Procesai keičiasi duomenimis, siųsdami ir gaudami pranešimus. Tam, kad
skirtingi pranešimai visada pasiektų teisingą adresatą, MPI yra apibrėžta komunikatoriaus sąvoka.
Komunikatorių sudaro procesų grupė ir papildomas požymis – kontekstas. Šį požymį automatiškai
generuoja MPI biblioteka ir jis yra unikalus. Ta pati procesų grupė gali priklausyti skirtingiems
komunikatoriams, bet pranešimai, pasiųsti net ir tarp tų pačių procesų, bet iš skirtingų komunikatorių,
nebus supainioti.
Komunikatoriai ypač svarbūs, kai programoje naudojame lygiagrečiųjų algoritmų bibliotekas. Jų
paprogramėse gali būti siunčiami pranešimai, tačiau kiekvienai paprogramei MPI apibrėžia naują
komunikatorių, todėl šie pranešimai nebus supainioti.
MPI_Init visada apibrėžia vieną komunikatorių MPI_COMM_WORLD, kuriam priklauso visi
sukurti procesai. Kiekvienos grupės procesai numeruojami nuo 0 iki P-1, čia P yra grupės procesų
skaičius. Tas pats procesas gali priklausyti keliems komunikatoriams ir jo numeriai skirtingose grupėse
nebūtinai sutampa. MPI funkcija grąžina komunikatoriaus comm grupės elementų skaičių size.
MPI_Comm_rank. (MPI_Comm_rank (MPI_Comm comm, int *rank)). Ši MPI funkcija
nurodo besikreipiančio proceso eilės numerį (rank) tarp (comm) komunikatoriaus elementų.
MPI_Send. (MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int msgtag,
MPI_Comm comm)). Duomenų siuntimo funkcijos MPI_Send realizacija panaši į įprastinio laiško
siuntimą.
Pirmieji trys funkcijos MPI_Send argumentai apibrėžia pranešimo turinį. Pirmasis argumentas
(buff) nurodo buferio, iš kur bus dedami duomenys, pradžios adresą, antrasis argumentas (count)
12
nurodo duomenų kiekį, o trečiasis argumentas (datatype) nurodo duomenų tipą. Taigi pranešimo ilgis
yra matuojamas ne baitų skaičiumi, o tam tikro duomenų tipo elementų skaičiumi. Taip padaryta todėl,
kad lygiagretusis kompiuteris gali būti heterogeniškas, o skirtingų tipų procesoriuose arba operacinėse
sistemose net ir to paties tipo skaičiai gali būti skirtingo ilgio. Todėl, norėdami teisingai užkoduoti ir
iškoduoti siunčiamą informaciją, apibrėžiame universalius MPI duomenų tipus. Ketvirtasis funkcijos
argumentas (dest) nurodo numerį proceso, kuriam skirtas pranešimas. Kadangi procesai yra
numeruojami tik atitinkamos grupės atžvilgiu, tai nurodome ir komunikatorių (comm), kuriam
priklauso abu procesai. Priešpaskutinis argumentas (tag) pažymi pranešimą, todėl galime atskirti net ir
to pačio proceso atsiųstus pranešimus.
MPI_Recv. (MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int msgtag,
MPI_Comm comm, MPI_Status *status)). Ši MPI funkcija naudojama duomenų priėmimui. Funkcijos
MPI_Recv parametrai nusako:
buff – buferio, kur bus dedami duomenys, pradžios adresą;
count – priimamų duomenų kiekį;
dest – proceso, iš kurio gaunami duomenys, numerį;
tag – žymę;
comm – kompiuterių grupę, sujungtą į virtualią mašiną;
status – kitą informaciją.
MPI_Finalize. (MPI_Finalize ()). Visi procesai privalo įvykdyti šią funkciją. Tada sustabdomas
MPI bibliotekos darbas ir nė vienas procesas daugiau nebegali naudoti MPI funkcijų. Svarbu įsidėmėti,
kad toje pačioje programoje negalima antrą kartą įvykdyti MPI_ Init kreipinio.
Paminėsime dar keletą MPI funkcijų [12]:
MPI_Wtime. (MPI_Wtime(void)). Funkcija grąžina astronominį laiką sekundėmis, kuris yra
iškviečiant procesą.
MPI_Get_count. (MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count)).
Funkcijos MPI_Get_count parametrai nusako:
status – gauto pranešimo parametrai;
datatype – gauto pranešimo elementų tipas;
OUT count – pranešimo elementų skaičius.
Pagal parametro (status) reikšmę duotoji paprogramė nustato gautų (po kreipimosi į MPI_Recv)
arba gaunamų (po kreipimosi į MPI_Probe) elementų skaičių tipo (datatype).
MPI_Probe. (MPI_Probe(int source, int msgtag, MPI_Comm comm, MPI_Status *status)).
Funkcijos MPI_Probe parametrai nusako:
source – numeris proceso – siuntėjo arba MPI_ANY_SOURCE;
msgtag – laukiamo pranešimo žymė arba MPI_ANY_TAG;
13
comm – kurioje grupėje dirbame;
OUT status – surasto pranešimo parametrai.
Funkcija MPI_Probe nustato pranešimo gavimo faktą, tačiau pačio pranešimo ji nepriima.
MPI_Abort. (MPI_Abort(comm, errorcode)). Sustabdo visus MPI procesus, susijusius su
komunikatoriais. Ši funkcija sustabdo MPI veikimą, nežiūrint komunikatoriaus.
MPI_Get_processor_name. (MPI_Get_processor_name (*name, *resultlength)). Pateikia
procesoriaus, kurio komanda yra įvykdyta, pavadinimą. Taip pat grąžina pavadinimo ilgį.
MPI_Initialized. (MPI_Initialized (*flag)). Nurodo, ar MPI_Init buvo kviestas, ir grąžina loginę
reikšmę 1 (kviesta) arba 0 (nekviesta). MPI reikalauja, kad kiekvieno proceso metu MPI_Init būtų
kviečiamas tiktai vieną kartą. Tai gali sukelti modulių problemą, norint panaudoti MPI ir iškviečiant
MPI_Init. Todėl MPI_Initialized išsprendžia šią problemą.
MPI_Barrier. (MPI_Barrier (MPI_Comm comm)). Sustabdo procesų, iškvietusių duotą
procedūrą, darbą iki to momento, kol visi likę grupės comm procesai, taip pat įvykdys šią procedūrą
[1].
14
2. TIESINIŲ LYGČIŲ SISTEMŲ SPRENDIMO METODAI
Kai kalbama apie tiesinės algebros uždavinius, dažniausiai galvojama apie tiesinių lygčių
sistemų sprendimą. Šis uždavinių tipas, savaime yra vienas svarbiausių moksliniuose tyrimuose, be to
jis dar yra ir daugelio kitų užduočių bei algoritmų sudedamoji dalis, todėl šio tipo uždavinių svarba yra
neginčijama. Tai paaiškina ir nuolatinius bei nesibaigiančius mokslinius tyrimus ir tobulinimus šioje
srityje.
Tiesinių lygčių sprendimo metodai skaidomi į dvi grupes – tiesiniai ir iteraciniai. Šiame darbe
apžvelgsime abi šias metodų grupes ir pasistengsime palyginti lygiagrečiuosius šių metodų algoritmus.
2.1. Tiesinių lygčių sistemų apžvalga
Pradedant kalbėti apie tiesinių lygčių sprendimo metodus, pirma verta susipažinti su tiesinių
lygčių sistemomis.
Sistema išreikšta 1.1.1 formule vadinama tiesinių lygčių sistema.
11 1 12 2 1 1
21 1 22 2 2 2 2
1 1 2 2
... ...
... ...
...............................................................
... ...
r r m m
r r m m
n n nr r nm m n
a x a x a x a x b
a x a x a x a x b
a x a x a x a x b
+ + + + + =ìï + + + + + =ïíïï + + + + + =î
Čia: (1 ,1 )ija i m j n£ £ £ £ – yra lygties koeficientai;
1 2, ,..., nb b b – laisvieji nariai;
1 2, ,..., mx x x – nežinomieji arba kintamieji.
Šią sistemą galima užrašyti matricine lygtimi Ax=b (žr. 1.1.2 formulę) [8].
11 12 1 1 1
21 22 2 2 2
1 2
...
..., ,
... ... ... ... ... ...
...
m
m
n n nm m n
a a a x b
a a a x bA x b
a a a x b
æ ö æ ö æ öç ÷ ç ÷ ç ÷ç ÷ ç ÷ ç ÷= = =ç ÷ ç ÷ ç ÷ç ÷ ç ÷ ç ÷è ø è ø è ø
Čia: A – sistemos koeficientų matrica;
x –nežinomųjų (kintamųjų) vektorius;
b – laisvųjų narių vektorius.
Apibrėžimas. Tiesinių lygčių sistemos sprendiniu vadinamas toks nežinomųjų reikšmių rinkinys
1 2, ,..., mx x x , kuris tinka kiekvienai sistemos lygčiai [11].
(1.1.1)
(1.1.2)
15
Apibrėžimas. Jei X – sistemos sprendinių aibė, o ją sudarančių lygčių sprendinių aibės –
atitinkamai 1 2, ,..., nX X X , tai 1 2, ,..., nX X X yra sprendinių aibės X poaibiai – 1 2 ... nX X X X= I I I
[11].
Apibrėžimas. Kai tiesinių lygčių sistemos laisvieji nariai lygūs nuliui 0, (1 )ib i n= £ £ , sistema
vadinama homogeninė, kai bent vienas laisvasis narys yra nelygus nuliui 0, (1 )ib i n¹ £ £ , tai tokia
sistema yra nehomogeninė lygčių sistema [11].
Apibrėžimas. Dvi tiesinių lygčių sistemos vadinamos ekvivalenčiomis, jei jų sprendinių aibės
sutampa. Dvi tiesinių lygčių sistemos yra ekvivalenčios, jei viena jų gaunama iš kitos, atlikus baigtinį
elementariųjų pertvarkų skaičių [11].
Elementarieji pertvarkymai:
- sistemos lygčių sukeitimas vietomis,
- sistemos lygties padauginimas iš nelygaus nuliui skaičiaus,
- vienos sistemos lygties pridėjimas prie kurios nors kitos sistemos lygties [11].
Jeigu prie matricos A prijungsime laisvųjų narių stulpelį, tai gauta matricą vadinama išplėstąją
matrica ir žymima Ã.
Kronekerio ir Kapeli teorema. Tiesinių lygčių sistema yra suderinta tada ir tik tada, kai
sistemos matricos A ir išplėstosios matricos à rangai sutampa [8].
rangA rangA= %
Sistemos suderinamumas reiškia, kad lygčių sistema turi bent vieną sprendinį.
- jei rangA rangA n= =% , kur n nežinomųjų skaičius, sistema turi vienintelį sprendinį.
- jei rangA rangA n= <% , sistema turi be galo daug sprendinių.
- jei rangA rangA n= >% , sistema yra nesuderinta ir sprendinių neturi.
Apibrėžimas. Suderinta sistema vadinama apibrėžta, jei ji turi vienintelį sprendinį, ir
neapibrėžta, jei ji turi daugiau kaip vieną sprendinį [11].
2.2. Tiesiniai metodai
Tiesiniai metodai naudoja tam tikras formules nežinomiems kintamiesiems apskaičiuoti.
Rezultatas gaunamas po jau žinomo kiekio aritmetinių operacijų. Šie metodai palyginus yra paprasti ir
universalūs, t.y. tinka didesnei tiesinių lygčių sistemų klasei.
Tuo pačiu tiesiniai metodai turi daug trūkumų. Jie reikalauja saugoti atmintyje iškarto visą
matricą, o dideliems matricos dydžiams sunaudojama daug atminties. Be to dideliu šių metodų
(1.1.3)
16
trūkumu yra paklaidos skaičiavimo procese, nes esamos operacijos skaičiavimai reikalauja ankstesnių
operacijų rezultatų.
Tiesinius metodus kartais vadina tiksliais, nes skaičiavimai vyksta pagal tikslias formules su
sistemos koeficientais. Bet tikslus rezultatas gali būti gautas tik tiksliai vykdant skaičiavimus su
tiksliais sistemos koeficientais. Praktiškai sprendžiant tiesines lygčių sistemas kompiuteriu visada
daromos paklaidos. Todėl bus paklaidų ir rezultatuose [8], [4].
2.2.1. Gauso metodas
Gauso metodu vadinamas tiesinių lygčių sistemos sprendimo būdas, kai elementariaisiais
pertvarkiais eliminuojant nežinomuosius siekiama gauti tokią sistemą, kuri vadinasi trapecinė tiesinių
lygčių sistema, jei m<n (žr. 2.1.4 formulę) ir trikampė – jei m=n (žr. 2.1.2 formulę). Kai m=n, sistema
turi vieną sprendinį. Pirmuoju šios sistemos sprendimo žingsniu iš visų lygčių, išskyrus pirmąją,
pašalinamas nežinomasis x1. Tarkime, kad a11≠0, tada pirmoji lygtis dalijama iš a11, gautąją lygtį
dauginama iš ai1 ir atimama iš i-osios lygties, i=2,3,...,n. Pertvarkytosios lygties koeficientai
1 1ij ia f apskaičiuojami pagal 2.1.1 formuleę:
1 11 1 1 1,ij ij i j i i ia a a a f f a f= - = -
Čia: 1ija – pertvarkytosios lygties koeficientai;
1if – pertvarkytosios lygties laisvieji nariai.
Jeigu įstrižainės elementas a11=0, tai surandamas kitas pagrindinis elementas ai1≠0 ir prieš
pertvarkant tiesinių lygčių sistemą sukeičiamos vietomis i-oji ir j-oji lygtys.
Toliau šis procesas kartojamas su likusiomis lygtimis. Po (n-1) žingsnio tiesinių lygčių sistema
privedama prie tiesinių lygčių sistemos pavidalo su viršutine trikampe matrica (žr. 2.1.2 formulę).
1 12 2 1 1 1
2 2 2 2
... ...
... ...
...
k k n n
k k n n
n n
x c x c x c x d
x c x c x d
x d
+ + + + + =ìï + + + + =ïíïï =î
Čia: cii – pertvarkytosios į trikampę tiesinių lygčių sistemos koeficientai;
di – pertvarkytosios į trikampę tiesinių lygčių sistemos laisvieji nariai.
Šis Gauso metodo etapas vadinamas tiesiogine algoritmo eiga, jos metu apskaičiuojamas
elementas xn (žr. 2.1 pav.) [1].
(2.1.1)
(2.1.2)
17
2.1 pav. Gauso metodo tiesioginės algoritmo eigos i-ojo žingsnio schema.
Atbulinėje algoritmo eigoje, pradedant nuo xn-1, iš pertvarkytosios tiesinių lygčių sistemos
apskaičiuojami kiti sistemos nežinomieji pagal 2.1.3 formulę.
1
, 1, 2,...,1n
i i ij jj i
x d c x i n n= +
= - = - -å
Čia: xi – lygties kintamasis;
di – lygties laisvasis narys;
cij – lygties koeficientas.
Kai m<n – sistema yra neapibrėžta ir turi be galo daug sprendinių.
ïïî
ïïí
ì
=++
=++++=+++++
nnknkkk
nnkk
nnkk
bxaxa
bxaxaxa
bxaxaxaxa
...
....................................
......
......
222222
111212111
.
Trapecinė tiesinių lygčių sistema (žr. 2.1.4 formulę) turi be galo daug sprendinių. Parinkę bet
kurias nežinomųjų nkk xxx ,...,, 21 ++ reikšmes, pavyzdžiui, ),...,,( 2211 nnkkkk txtxtx === ++++ sistema
privedama prie trikampės k lygčių sistemos su k nežinomųjų pavidalo (žr. 2.1.5 formulę).
ïïî
ïïí
ì
---=
---=++---=+++
++
++
++
nknkkknkkk
nnkkkk
nnkkkk
tctcdxc
tctcdxcxc
tctcdxcxcxc
...
...........................................
......
......
11
211222222
111111212111
Čia: ),...,,( 21 nk ttt + – laisvai parinktas skaičių rinkinys.
(2.1.3)
(2.1.4)
(2.1.5)
18
Kadangi koeficientai 11 22, ,..., kkc c c nelygūs nuliui, tai ji turi vienintelį sprendinį kxxxx ,...,, 21= ,
atitinkanti laisvai pasirinktą skaičių rinkinį ),...,,( 21 nk ttt + . Todėl rinkinys (žr. 2.1.6 formulę) yra
sistemos sprendinys [10].
),...,,,,...,,( 2121 nkk tttxxx +
Apibrėžimas. Jei gauname lygtį pavidalo 1 20 0 ... 0 ,nx x x d+ + + = kur d≠0, tai sistema
sprendinių neturi. Jei gauname lygtį pavidalo 1 20 0 ... 0 ,nx x x d+ + + = kur d=0, tai tapatybę iš sistemos
pašaliname [10].
2.2.2. Gauso ir Žordano metodas
Gauso ir Žordano metodu vadinamas bendrojo pavidalo (žr. 1.1.1 formulę) tiesinių lygčių
sistemos sprendimo būdas, kai elementariaisiais pertvarkiais eliminuojant nežinomuosius siekiama
gauti diagonalinę tiesinių lygčių sistemą (žr. 2.2 pav. ir 2.1.7 formulę)
ïïî
ïïí
ì
====
nnnn dxc
dxc
dxc
...00
...............
0...0
0...0
2222
1111
.
Šios sistemos koeficientai c11,c22,...cnn nelygūs nuliui. Ši sistema turi vienintelį sprendinį (žr.
2.1.8 formulę).
÷÷ø
öççè
æ
nn
n
cd
cd
cd
,...,,22
2
11
1
2.2 pav. Gauso ir Žordano metodo schema
(2.1.6)
(2.1.7)
(2.1.8)
19
2.2.3. Kramerio formulės
Turime tiesinių lygčių bendrojo pavidalo (žr. 1.1.1 formulę) sistemą. Tiesinių lygčių sistema yra
kvadratinė, t.y. stulpelių ir eilučių skaičius yra vienodas ir žymimas n.
Sudarykime šios sistemos koeficientų matricą A (žr. 2.1.9 formulę)
÷÷÷÷÷
ø
ö
ççççç
è
æ
=
nnnn
n
n
aaa
aaa
aaa
A
...
............
...
...
21
22221
11211
Čia: aij – sistemos koeficientai.
Pažymėkime matricos A determinantą Δ (žr. 2.1.10 formulę).
nnnn
n
n
aaa
aaa
aaa
...
............
...
...
21
22221
11211
=D .
Tarkime, kad Δ≠0. Determinanto Δupirmąjį stulpelį pakeitus laisvųjų narių b1,b2,..,bn stulpeliu
gaunamas determinantas Δ1 (žr. 2.1.11 formulę).
nnnn
n
n
aab
aab
aab
...
............
...
...
2
2222
1121
1 =D .
Determinanto ΔË antrąjį stulpelį pakeitus laisvųjų narių b1,b2,...,bn stulpeliu gaunamas Δ2
determinantas (žr. 2.1.12).
nnnn
n
n
aba
aba
aba
...
............
...
...
1
2221
1111
2 =D .
Analogiškai, determinanto ΔËtrečiasis stulpelis pakeičiamas laisvųjų narių b1,b2,...,bn stulpeliu,
determinanto Δuketvirtasis stulpelis pakeičiamas laisvųjų narių b1,b2,...,bn stulpeliu ir t.t., kol galiausiai
determinanto ΔËn-tasis stulpelis pakeičiamas laisvųjų narių b1,b2,...,bn stulpeliu.
Kramerio formulėmis vadinamos 2.1.13.formulės.
DD
=DD
=DD
= nnxxx ,...,, 2
21
1
O duotos tiesinių lygčių sistemos sprendinys yra toks rinkinys [15], [16]:
),...,,( 21 nxxx
(2.1.9)
(2.1.10)
(2.1.11)
(2.1.12)
(2.1.13)
(2.1.14)
20
2.2.4. Atvirkštinės matricos metodas
Turime tiesinių lygčių bendrojo pavidalo (žr. 1.1.1 formulę) sistemą. Tiesinių lygčių sistema yra
kvadratinė.
Tarkime, kad matricos determinantas Δ≠0, tada lygčių sistema vadinama neišsigimusiąją
(priešingu atveju, kai Δ=0, sistema vadinama išsigimusiąją). Jei tiesinių lygčių sistema yra
neišsigimusioji, egzistuoja atvirkštinė matrica A-1. Padauginkime matricinės lygties Ax=b (žr. 1.1.2
formulę) abi puses iš kairės iš matricos A-1:
1 1( )A Ax A b- -=
1 1( )A A x Ex x A b- -= = =
Čia: A-1 – atvirkštinė matrica;
E – vienetinė matrica.
Iš matricinės lygties galima gauti x=A-1b. Tai ir yra duotos tiesinių lygčių sistemos sprendinys
[10], [16].
2.2.5. Tiesinių homogeninių lygčių sistemos sprendimas.
Nagrinėjama tiesinių homogeninių lygčių sistema (žr. 2.1.17 formulę)
ïïî
ïïí
ì
=+++
=+++=+++
0...
...........................................
0...
0...
2211
2222121
1212111
nnnnn
nn
nn
xaxaxa
xaxaxa
xaxaxa
.
Ši sistema visada suderinta, nes rangas rangA rangA= % . Todėl sistema turi bent vieną sprendinį.
Visada tokios sistemos sprendinys yra x1=x2=...=xn=0. Šis sprendinys vadinamas nuliniu arba
trivialiuoju sprendiniu. Jei rangA<n, tuomet sistema turės be galo daug sprendinių [16].
2.3. Iteraciniai metodai
Iteraciniai metodai – tai metodai su nuosekliais artiniais. Juose būtina turėti pradinį artinį, o po to
įvykdomas vienas skaičiavimu ciklas vadinamas iteracija. Iteracijos rezultate gaunamas naujas artinys.
Iteracijos vykdomos tol, kol bus surastas artinys, kurio reikšmė bus artima rezultato reikšmei pagal
nustatytą tikslumą.
Didelis iteracinių metodų privalumas yra tas, kas skaičiavimų paklaidos nesikaupia, nes
kiekvienos esamos iteracijos rezultatas nepriklauso nuo ankstesnių iteracijų skaičiavimų [8], [4].
(2.1.15)
(2.1.16)
(2.1.17)
21
2.3.1. Paprastų iteracijų metodas
Laikykime, jog egzistuoja tiesinių lygčių sistemos (žr. 1.1.1 formulę) vienintelis sprendinys.
Įvairūs paprastų iteracijų metodai susiję su bendrojo pavidalo (žr. 1.1.1 formulę) sistemos perėjimu
prie pavidalo (žr. 2.2.1 formulę)
ïïî
ïïí
ì
------=
------=------=
++--
++
nknkkkknknnknk
nnkk
nnkkkk
tctcxcxcdxc
tcxcxcxcdxc
tctcxcxcdxc
......
...........................................................................
......
......
111111
223231212222
111112121111
.
Atsižvelgiant į 2.2.1 išraišką galima suformuluoti paprastą iteracinį procesą (žr. 2.2.2
formulę)[4]
;)(1 bxAADx kk ++-= +-+
Čia: 0x – pradinis kintamasis;
D – matricos A įstrižainė;
A- - matricos A dalis žemiau įstrižainės;
A+ – matricos A dalis virš įstrižainės;
k = 0,1,.. – iteracijos numeris.
Jeigu didinant iteracijos skaičių artinio reikšmė artėja iki tikslaus sprendinio (žr. 2.2.3 formulę)
tai iteracinis procesas artėja link sprendinio.
xxk
k=
®¥lim .
Praktiškai realizuojant paprastų iteracijų metodą, tam, kad pasiekti reikiamo taško yra
palyginami tarpusavyje artiniai apskaičiuojami dviejuose iš eilės einančiuose iteracijose kx ir 1+kx . Jei
1+kx mažai skiriasi nuo kx procesas sustabdomas.
Tam, kad apibrėžti kaip mažai skiriasi du artiniai, naudojami keli būdai. Vienas iš jų, nustatyti
paklaidos dydį 0>e . Tai konvergavimo sąlygos būtų (žr. 2.2.4 ir 2.2.5 formules)[14]
e<-=- å=
++n
i
ki
ki
kk xxxx0
211 )(||
e<-+
<<||max 1
1
ki
ki
nixx
Čia: ε – paklaida.
2.3.2. Iteracinis Jakobio metodas
Sprendžiame bendro pavidalo tiesinių lygčių sistemą (žr. 1.1.1 formulę). Tiesiogiai taikant
Jakobio metodą gauname sistemą (žr. 2.2.6 formulę).
(2.2.1)
(2.2.2)
(2.2.3)
(2.2.4)
22
ïïïï
î
ïïïï
í
ì
------=
------=
------=
--++
++--
++
nn
nnn
nn
knk
nn
knk
nn
n
nn
nn
kk
nkn
kk
kkk
kk
knk
kk
n
kk
kk
nnkkkk
a
xa
a
xa
a
xa
a
xa
a
bx
a
xa
a
xa
a
xa
a
xa
a
bx
a
xa
a
xa
a
xa
a
xa
a
bx
111111
111111
11
1
11
111
11
1
11
212
11
11
......
.......................................
......
.......................................
......
Tiesiogiai taikomas Jakobio metodas yra toks: iš pirmos lygties išreiškiamas x1, iš antros lygties
išreiškiamas x2 ir t.t. (prieš tai lygčių vietomis nesukeičiame). Svarbu tai, kad čia reikia, jog būtų
a11≠0,a22≠0,...,ann≠0, t.y. ne kiekvienai lygčių sistemai galima tiesiogiai taikyti Jakobio metodą.
Modifikuotas Jakobio metodas yra toks, kuriame prieš tai sukeičiamos lygtys (t.y. matricos A
eilutes bei laisvuosius narius bi) vietomis (galima keisti ir matricos A stulpelius vietomis, kas atitiktų
kintamųjų xi pernumeravimą, bet paprasčiau yra keisti tik eilutes) ir šitaip gautai lygčių sistemai
tiesiogiai taikomas Jakobio metodas. Dažniausiai lygtys sukeičiamos taip: pirma lygtis yra ta, kurioje
yra moduliu didžiausias koeficientas prie x1, antra lygtis yra ta, kurioje iš likusių lygčių yra moduliu
didžiausias koeficientas prie x2 ir t.t. [2],[4].
Iteracinis procesas yra toks:
},...,2,1{,,1
1 nixa
a
a
bx
n
ijj
kj
ii
ij
ii
iki Î-= å
¹=
-
Čia: 1-kix – yra prieš tai apskaičiuota kintamojo apytikslė xi reikšmė;
kix – dabar apskaičiuota reikšmė (k-tasis artinys).
Sakoma, kad iteracinis procesas konverguoja (žr. 2.2.7 formulę), jeigu didinant iteracijų skaičių
artiniai artėja prie tikslių reikšmių (žr. 2.2.3 formulę). Priešingu atveju iteracinis procesas diverguoja.
Pažymėkime matricą Jl (žr. 2.2.8 formulę)
÷÷÷÷÷
ø
ö
ççççç
è
æ
=
nnnn
n
n
aaa
aaa
aaa
J
l
ll
l
...
............
...
...
21
22221
11211
.
Teorema. Tam, kad Jakobio metodas (žr. 2.2.7 formulę) konverguotų turi būti tenkinama būtina
ir pakankama sąlyga – visi lygties 0)det( =lJ šaknų moduliai turi būti mažesni už vienetą [2].
Teorema. Kad Jakobio metodas (žr. 2.2.7 formulę) konverguotų pakanka, kad galiotų viena iš
šių sąlygų:[2]
å¹=
<Î"n
ijjiiij aani
,1
||||:},...,2,1{
(2.2.6)
(2.2.7)
(2.2.8)
(2.2.9)
23
å¹=
<Î"n
ijj ii
ij
a
ani
,1
1:},...,2,1{
å å= ¹=
<n
j
n
ijjij
jj
aa1 ,1
22
1||1
Čia: aij – sistemos koeficientai.
2.3.3. Zeidelio metodas
Zeidelio metodas nuo Jakobio metodo skiriasi tik tuo, kad viename iteraciniame žingsnyje
naudojami ne vien tik prieš tai buvusios iteracijos artiniai 1-kix (kaip yra Jakobio metode), bet
panaudojami ir tie artiniai, kurie jau yra apskaičiuoti šioje iteracijoje.
Lygiai taip pat kaip ir Jakobio metode, yra tiesiogiai taikomas Zeidelio metodas (t.y. nekeičiant
lygčių vietomis išreiškiami pagrindinėje įstrižainėje esantys elementai) ir modifikuotas Zeidelio
metodas (iš pradžių lygtys yra sukeičiamos ir tada išreiškiami diagonaliniai elementai).
Zeidelio metodo iteracinis procesas išreiškiamas 2.2.12 formule [2].
},...,2,1{,1
1 1
1 nixa
ax
a
a
a
bx
i
j
n
ij
kj
ii
ijkj
ii
ij
ii
iki Î--= å å
-
= +=
- .
Pažymėkime matricą Zl (žr. 2.2.13 formulę)
÷÷÷÷÷
ø
ö
ççççç
è
æ
=
nnnn
n
n
aaa
aaa
aaa
Z
l
ll
l
...
............
...
...
21
22221
11211
.
Teorema. Tam, kad Zeidelio metodas (žr. 2.2.12 formulę) konverguotų turi būti tenkinama
būtina ir pakankama sąlyga – visi lygties 0)det( =lZ šaknų moduliai turi būti mažesni už vienetą [2].
Teorema. Kad Zeidelio metodas (žr. 2.2.12 formulę) konverguotų pakanka, kad galiotų viena iš
2.2.9, 2.2.10 ir 2.2.14 sąlygų [2].
Matrica A yra simetrinė ir teigiamai apibrėžta
Teorema. Jeigu matrica A yra simetrinė ir jos pagrindinės įstrižainės elementai yra teigiami, tai
norint, kad Zeidelio metodas konverguotų yra būtina, jog matrica A būtų teigiamai apibrėžta [2].
Teorema. Jeigu galioja 2.2.9 sąlyga, tai Zeidelio metodas konverguoja greičiau negu Jakobio
metodas [2].
Bendru atveju konvergavimas (t.y. artėjimas) gali priklausyti nuo to, kokios paklaidos prasme
nagrinėjamas artėjimas, t.y. gali būti taip, kad vienos paklaidos prasme konverguoja (paklaida artėja į
nulį), o kitos paklaidos prasme nekonverguoja (paklaida neartėja į nulį). Tačiau sprendžiant tiesinių
lygčių sistemą su realiais koeficientais turime erdvę Rn. Funkcionalinėje analizėje įrodyta, kad
(2.2.10)
(2.2.11)
(2.2.12)
(2.2.13)
(2.2.14)
24
baigtinio matavimo erdvėse visos normos yra ekvivalenčios. Todėl jeigu aibėje Rn kokia nors seka
konverguos vienos normos prasme, tai ta seka būtinai konverguos ir kitos normos prasme (tik, galbūt,
skirtingu greičiu).
Bendrojo pavidalo (žr. 1.1.1formulę) tiesinių lygčių sistemos sprendinys yra vektorius
),...,,( 21 nxxx . Šio sprendinio artinys yra vektorius ),...,,( 21kn
kkk xxxx = . Šių vektorių skirtumo norma
||xk - x|| yra paklaida. Bendru atveju paklaida gali būti ir bet kokia atstumo funkcija, kuri nebūtinai yra
suderinta norma.
Pateikiamos tokios dvi paklaidos (žr. 2.2.15 ir 2.2.16 formules) [2]
( )nkn
kkk xxxxxxxx ---=-=D ,...,,max 221111
å=
-=-=Dn
ii
ki
k xxxx1
22 .
(2.2.15)
(2.2.16)
25
3. EKSPERIMENTINIS TYRIMAS
Šiame darbe naudojami 14 Pentium 4 tipo kompiuterių, sujungtų į lokalųjį tinklą (100 Mb/s),
naudojant Windows XP operacinę sistemą.
Lygiagrečių uždavinių sprendimui kompiuterių tinkle naudojamas programinis paketas MPICH
v.1.2.5.
Duomenims persiųsti naudojamas paketas MPICH, kuris gali veikti tik su programomis,
sukurtomis naudojant ne žemesnę kaip Microsoft Visual C++ 6.0 versiją. Duomenų apdorojimui ir
pateikimui buvo naudojamos MS Office programos.
Pirmam eksperimentui pasirinktas lygiagretusis algoritmas realizuojantis Jakobio iteracinį
metodą.
3.1. Lygiagretusis Jakobio iteracinio metodo algoritmas
Kalbant apie Jakobio metodo realizavimą reikia apgalvoti lygiagrečiojo algoritmo sudarymo
etapus. Vienas pagrindinių žingsnių yra užduočių paskirstymas procesoriams, bet visų pirmą reikia
nustatyti, kurias užduotys galima vykdyti lygiagrečiai. Sekanti sistema (žr. 3.1.1 formulę) puikiai
atvaizduoja Jakobio metodo esmę [4].
),...,,(
...
),...,,(
),...,,(
211
2121
2
2111
1
kn
kkn
kn
kn
kkk
kn
kkk
xxxfX
xxxfX
xxxfX
=
=
=
+
+
+
Užduotimi Tk laikysimas k-ojoje iteracijoje Xk+1 apskaičiavimas. Vienoje iteracijoje yra n
užduočių. Apskaičiavimas kiekvienos vektoriaus komponentės k+1-osios iteracijos priklauso nuo
ankstesnėje k-ojoje iteracijoje apskaičiuotų komponenčių, bet nepriklauso tarpusavyje. Todėl
lygiagretinant šį metodą galima pasiūlyti sekanti algoritmą.
Apskaičiuojamų komponenčių kiekį kiekvienam procesui galima apskaičiuoti sekančiu būdu (žr.
3.1.2 formulę) [4]
1 0, {0,..., }p p
n ns s kur s
p p-= + Î
Čia: n – matricos A eilučių skaičius;
p – procesų skaičius.
Tokiu atveju X vektoriai bus paskirstyti procesams sekančiu būdu (žr. 3.1 pav.)
(3.1.1)
(3.1.2)
26
3.1 pav. Užduočių pasiskirstymas procesams.
Kiekviena iteracija susidės iš žingsnių:
1 žingsnys. Kiekvienam procesui p apskaičiuos s kiekį nežinomųjų pagal 3.1.3 formulę [4].
1
1,
,n
sjk kss j
j j sss ss
abx x
a a-
= ¹
= - å
Čia: s – komponenčių kiekis kiekvienam procesui p apskaičiuoti (žr. 3.1.2 formulę).
2 žingsnis. Kiekvienas procesas p persiunčia visiems kitiems s vektoriaus x apskaičiuotų
komponenčių ir patikrinama bus sustojimo sąlyga. Be to paklaida ε bus apskaičiuojama pirmojo
proceso pagal 2.2.5 formule ir persiųsta kitiems [4].
Eksperimento rezultatai
Eksperimentai buvo atliktas naudojant įvairių dydžių matricas bei procesų skaičius. Parinkti
buvo matricos dydžiai n=100, 1000, 2000, 4000 ir 6000 bei procesų kiekiai p=2, 4, 6, 8, 10, 12, 14.
Išgautus rezultatus iliustruoja pateikta 3.1 lentelė.
Lentelė 3.1. Jakobio metodo algoritmo vykdymo laikas. Matricos dydis (n) Procesų
skaičius 100×100 1000×1000 2000×2000 4000×4000 6000×6000
1 0.02189 0.216475 0.667747 9.618215 161.22664
2 0.06842 0.818517 3.289458 27.99165 146.26566
4 0.0446 1.716386 8.379886 62.63436 223.27527
6 0.10843 2.142526 9.105451 82.04828 341.28933
8 0.50916 2.148011 9.431709 76.02445 317.57258
10 2.17713 3.865673 13.653399 47.9032 151.97667
12 2.57354 4.378646 12.076756 45.49711 126.83343
14 2.22608 4.865744 11.847331 54.926 139.7947
11 21 1
12 1 22
11 1 1 2
11 2
11 22 1 2 1
11 2
( , ,..., )
... 2
( , ,..., )
( , ,..., )
..
( , ,..., )
... 1
( , ,..
.
( ,.
)
,
.,
k k k kn n n
p p
k k
k k k
k k k kn
kn
k k k kn n n
k kn n
n np p
k k kn n
np p
p p
X f x x x
asis
X f x x x
asis proce
proce
X f x x x
sas
X f x x x
sas
X f x x
X f
x
x x
++ +
+
+
+
++ +
+
=
-
=
=
=
=
-
=
.., )kn
n asis procesas
x
-
(3.1.3)
27
3.2 a)-e) paveikslėliuose pateiktose diagramose parodyti iteracinio Jakobio metodo lygiagrečiojo
algoritmo vykdymo laikai.
a)
Algoritmo vykdymo laikas, kai matricos dydis 100×100
0
0.5
1
1.5
2
2.5
3
1 2 4 6 8 10 12 14
Procesų skaičius
Lai
kas,
sek
b)
Algoritmo vykdymo laikas, kai matricos dydis 2000×2000
0
2
4
6
8
10
12
14
16
1 2 4 6 8 10 12 14
Procesų skaičius
Lai
kas,
sek
c)
Algoritmo vykdymo laikas, kai matricos dydis 1000×1000
0
1
2
3
4
5
6
1 2 4 6 8 10 12 14
Procesų skaičius
Lai
kas,
sek
d)
Algoritmo vykdymo laikas, kai matricos dydis 4000×4000
0
10
20
30
40
50
60
70
80
90
1 2 4 6 8 10 12 14
Procesų skaičius
Lai
kas,
sek
e)
Algoritmo vykdymo laikas, kai matricos dydis 6000×6000
0
50
100
150
200
250
300
350
400
1 2 4 6 8 10 12 14
Procesų skaičius
Lai
kas,
sek
3.2 pav. Iteracinio Jokobio algoritmo vykdymo laikas
Iš gautų rezultatų galima teigti, jog mažoms matricoms iteracinio Jakobio metodo lygiagrečiojo
algoritmo laikas nėra mažesnis už nuosekliojo. Tačiau tiesinių lygčių sistemos, kurios dydis n=6000,
sprendimą realizuojančio lygiagrečiojo algoritmo laikas yra mažesnis nei nuosekliojo. Kadangi
eksperimentas buvo vykdomas 100 Mb/s tinkle, galima teigti, jog mažų užduočių skaičiavimo laikas
yra mažas palyginus su duomenų perdavimo kaštais.
28
3.2. Lygiagretieji Gauso metodo algoritmai
Antrajam ir trečiajam eksperimentui buvo pasirinktas Gauso metodas. Lygiagretaus algoritmo
sudarymui pirma aptarsime ir nustatysime sprendimo užduotis.
Laikysime, kad F vektorius yra saugomas A matricos (n+1)-ajame stulpelyje. Gauso metodo
algoritmą sudaro tris ciklai, skirtingai juos išdėstydami gaunami šeši metodo realizavimo variantai.
Dabar pateiksimas Gauso metodo variantas, kai vidiniame cikle modifikuojamas visas stulpelis.[1]
Gauso metodo tiesioginės eigos algoritmas
for (k = 1; k <= n; k++)
for (j = k + 1; j <= n + 1; j++)
{ [užduotis Tkj]
tkj = tkj / tkk;
for (i = k + 1; i <= n; i++)
tij =tij – tik ×tkj;
}
Užduotimi Tkj laikysime algoritmo k-ojo žingsnio j-ojo stulpelio pertvarkymą, jų iš viso turime
( 1)2
n n +. Ne visos šios užduotys gali būti vykdomos nepriklausomai. Pažymėkime ij klT Tp sąlygą, kad
užduotis Tkl gali būti pradėta skaičiuoti tik tada, kai pasibaigė Tij. Jeigu šios užduotys vykdomos
skirtinguose procesoriuose, tai procesorius, kuris įvykdė užduotį Tij, nusiunčia pranešimą procesoriui,
kuris skaičiuos užduotį Tkl. Bendrosios atminties kompiuteriuose sinchronizacija pasiekiama
specialiomis programinėmis priemonėmis [1].
Gauso algoritme gaunamos tokios užduočių priklausomybės
, 1 1,
, 1,
, 1 ( 1)k k k j
k j k j
T T k j n
T T+ +
+
£ < £ +p
p
Čia: Tkj – proceso užduotis.
Pirmoji 3.2.1 sąsaja reiškia, kad (k+1)-ojo žingsnio užduotys gali būti pradėtos vykdyti tik tada,
kai k-ajame žingsnyje jau apskaičiuotas (k+1)-asis matricos stulpelis. Antroji 3.2.1 sąsaja reiškia, kad
j-ojo stulpelio pertvarkymas (k+1)-ajame žingsnyje gali prasidėti tik tada, kai jau atliktas šio stulpelio
pertvarkymas k-ajame žingsnyje. Taigi visas vieno žingsnio užduotis (žr. 3.2.2 formulę) galima
skaičiuoti nepriklausomai tuo pačiu metu.
{ }, 1 , 2 , 1, ,...,k k k k k nT T T+ + +
Pereisime prie užduočių pasiskirstymo procesoriams etapo. Šiame etape svarbu yra:
- tolygiai paskirstyti užduotis procesoriams;
(3.2.1)
(3.2.2)
29
- minimizuoti duomenų persiuntimo procesoriams kaštus.[1]
Eksperimentams pasirinkti buvo du populiariausieji užduočių paskirstymo algoritmai: blokinis ir
ciklinis duomenų paskirstymas.
3.2.1. Lygiagretusis blokinio duomenų paskirstymo Gauso metodo algoritmas
Tarkime, kad turime p procesorių. Tada kiekvienas procesorius skaičiuoja užduotis, skirtas
pn
r = iš eilės einantiems matricos stulpeliams pertvarkyti. Taigi k-asis procesorius gauna užduotis (žr.
3.2.3 formulę)
)1(0)},1(1),1()2(,{ -££-££++££+= pkjikrrjkrTT ijk
Nulinis procesas sprendžia užduotis Tij, j=1,2,...,r, pirmasis procesorius užduotis Tij,
j=r+1,r+2,...,2r ir taip toliau. Kadangi visos j-ojo stulpelio užduotys priklauso tam pačiam
procesoriui, tai realizuojant topologinį ryšį , 1,k j k jT T +p nereikia siųsti papildomo pranešimo, o užtenka
tik atitinkamai sudaryti užduočių vykdymo tvarkaraštį.
Jeigu n nėra skaičiaus p kartotinis, tai apskaičiuojama pagrindinė bloko dalis, kuri yra lygi
santykio pn sveikajai daliai ú
û
ùêë
é=
pn
r , randama liekana q=n–pr ir pirmiesiems q procesoriams
skirstoma po (r+1) matricos stulpelį [1].
Lygiagretaus Gauso metodo algoritmo blokinis duomenų paskirstymas tarp procesų pavaizduotas
3.3 pav.
0,0 0,
1,0 1,
2,0 2
0, 0,0, 1 0,2
1, 1 1,2
2, 1 2,2
2
,
2,0 2
1,
,
1,
2,
, 1 2
2
0
,
,
1
2
2
...
...
...
...
.
...
...
...
.
..
.. ... ...
.
... ...
...
...
...
..
... ... .
...
... ... ...
.. ....
..
r r
r r
r
r
r
r
n r n
n r n
n r nr
kk k r k r k r
a a
a a
a a
a a
b
b
a a a
a a
a
a a
a a
aa
ba a
a
-
-
+
+
+
- + -
-
- -
1,
2
0
, 2,
1, 1,
, ,
1, 1 1,2
, 1 ,2
2, 1
2
11,
,0 ,
2,0 2 2, 2 2,,
...
...
... ..
...
...
... ... ...
...
...
...
.
...
...
... ... ...
.
...
.
...
... ... ...
.. ..
k r k r
k r k r
k
k
k
n r k n
k n r k n
k n r k n
k
n
k r
k k r
n n r r nn n rr
a a
a a
a a
b
b
a
a a
a a
a a
a a
ba
a
a
a
-
- -
-
-
- + -
+
- +
- -
- - -
-
- --
-
-
1,0
2
1
2,
1, 1,1, 1 1,2
, 1 ,
1,
, ,0 2, ,
.....
...
...... .
. .... .. ..
n
nn
n
n r
n n r
n r n r
n
n
n n r n n
n n r nn r n nr
b
b
b
a a
a
a a
a a
a
a
a
a a-
-
- -- --
-
+
+ -
- -
3.3 pav. Gauso metodo lygiagretaus algoritmo blokinio duomenų padalijimo tiesioginė eiga.
Aktyvi eilutė, k-1 iteracija
Aktyvi eilutė, 1 iteracija Aktyvi eilutė, 2
iteracija Aktyvi eilutė, 3 iteracija
Aktyvi eilutė, k-2 iteracija
Aktyvi eilutė, k iteracija
Aktyvi eilutė, n-2 iteracija Aktyvi eilutė, n-1
iteracija
Pirmas procesas Antras procesas p-asis procesas
(3.2.3)
30
Eksperimento rezultatai
Kaip ir pirmo eksperimento metu buvo parinkti matricos dydžiai n=100, 1000, 2000, 4000 ir
6000 bei procesų kiekiai p=2, 4, 6, 8, 10, 12, 14.
Eksperimentų rezultatus iliustruoja 3.2 lentelė ir 3.4 a)-e) paveikslėliuose pateiktos diagramos.
Lentelė 2.2. Blokinio duomenų paskirstymo Gauso metodo algoritmo vykdymo laikas. Matricos dydis (n) Procesų
skaičius 100×100 1000×1000 2000×2000 4000×4000 6000×6000
1 0.012232 3.369733 25.837256 204.064712 731.485278
2 0.054298 3.276017 19.041277 132.163976 454.100544
4 0.103997 3.665316 16.842018 96.895356 325.735114
6 0.185863 4.324584 17.915735 89.872016 254.167309
8 0.203176 5.044007 25.299121 86.379907 240.100511
10 0.223335 5.168389 226.261794 311.010368 536.87988
12 0.314829 5.736687 357.873567 518.292527 913.49896
14 0.377977 7.52562 425.250778 578.862966 1291.031106
a)
Algoritmo vykdymo laikas, kai matricos dydis 100×100
0
0.1
0.2
0.3
0.4
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
b)
Algoritmo vykdymo laikas, kai matricos dydis 1000×1000
0
2
4
6
8
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
c)
Algoritmo vykdymo laikas, kai matricos dydis 2000×2000
0
100
200
300
400
500
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
d)
Algoritmo vykdymo laikas, kai matricos dydis 4000×4000
0100200300400500600700
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
31
e)
Algoritmo vykdymo laikas, kai matricos dydis 6000×6000
0
200
400
600
800
1000
1200
1400
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
3.4 pav. Gauso metodo blokinio duomenų pasiskirstymo algoritmo vykdymo laikas
Kaip ir Jakobio metodo Gauso blokinio duomenų pasiskirstymo algoritmo vykdomo laikas nėra
mažesnis sprendžiant mažas tiesinių lygčių sistemas. Tačiau skirtingai nei pirmame eksperimente šio
lygiagrečiojo algoritmo vykdymo laikas, realizuojantis tiesinių lygčių sistemos, kurios dydis n=1000,
sprendimą, sumažėjo naudojant 2 procesus. Iteracinio Jakobio metodo lygiagrečiojo algoritmo
vykdymo metu laiko sumažėjimas stebimas tik pateikiant tiesinių lygčių sistemos dydžiui n=6000.
3.2.2. Lygiagretusis ciklinio duomenų paskirstymo Gauso metodo algoritmas
Šiame algoritme gretimiems procesoriams skiriamos užduotys, atitinkančios gretimus matricos
stulpelius. Tada k-ojo procesoriaus užduočių sąrašas yra (žr. 3.2.4 formulę)
{ , : mod( 1), 1 ( 1)}, 0 ( 1)k ijT T j k j i j k p= = - £ £ - £ £ -
3.3. lentelėje pateikti blokinio ir ciklinio aštuonių stulpelių matricos padalijimo duomenys trims
procesoriams. Nurodyta, kuris procesorius gauna atitinkamą stulpelį esant abiems padalijimams [1].
Lentelė 3.3. Blokinis ir ciklinis matricos stulpelio padalijimas Stulpelio Nr. Ciklinis duomenų
padalijimas
Blokinis duomenų
padalijimas
1 0 0
2 1 0
3 2 0
4 0 1
5 1 1
6 2 1
7 0 2
8 1 2
(3.2.4)
32
Lygiagretaus Gauso metodo algoritmo ciklinis duomenų paskirstymas tarp procesų pavaizduotas
3.5 pav.
00,1
1,1
2,1
2
0,0
1,0
2,0
2,0
1,0
,0
2,0
1,0
,
,1
1,1
,1
1,1
1
,
1,
2,
2,
1,
,
2,
1
,
, ,
,10
1
... ...
... ...
... ...
... ...
... ...
... ..
...
...
...
.
...
...
...
.
...
..
....
...
.
r
r
r
k r
k r
k r
n r
n r
n r
k
k
k
k
nn
n
k
k
n
n
n
aa
a a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a a
a
a
a
a
-
-
-
-
-
-
--
-
-
-
-
0,
1,
2,
2,
1,
,
2,
1,
0, 1
1, 1
2, 1
2, 1
1, 1
, 1
1, 1
1, 1
, , 1
...
...
...
...
...
. ...
... ...
... ..
...
.
... ...
...
...
...
..
...
..
.
.
n r
n r
n r
n r
n r
n r
k n r
k n r
k n r
n n r
n n r
n
k n r
k n r
k n r
n n r
n n r
n rn r n
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
aa
- +
-
-
-
-
- -
- -
-
-
+
- +
- - +
- - +
- +
- - +
- - +
- +
-
- -
-
0
1
2
2
1
0,
1,
2,
2,
1,
1
,
2,
1,
2
,
...
...
..
...
...
.
n
n
n
k n
k n
k n
n n
k
k
k
n
n
n
n n
n n
a
a
a
a
a
b
b
b
b
b
b
b
a
a
a
a
b
b
-
-
-
-
-
-
-
-
3.5 pav. Gauso metodo lygiagretaus algoritmo ciklinio duomenų padalijimo tiesioginė eiga.
Eksperimento rezultatai
Trečio eksperimento metu buvo parinkti matricos dydžiai n=100, 1000, 2000, 4000 ir 6000 bei
procesų kiekiai p=2, 4, 6, 8, 10, 12, 14.
3.4 lentelė iliustruoja eksperimento rezultatus.
Lentelė 3.4. Ciklinio duomenų paskirstymo Gauso metodo algoritmo vykdymo laikas. Matricos dydis (n) Procesų
skaičius 100×100 1000×1000 2000×2000 4000×4000 6000×6000
1 0.004068 3.700663 30.337317 580.958081 7363.918741
2 0.056807 3.320762 20.430863 306.311202 4056.721710
4 0.322819 8.779371 62.245130 176.735237 2090.941257
6 1.335414 12.059488 75.247570 141.530290 1469.891612
8 1.678939 22.559592 85.810021 168.920810 1156.144203
10 2.336691 25.174908 333.326066 491.030873 1482.288503
12 2.520128 30.334474 350.686296 533.717491 2074.661573
14 2.512186 85.461889 423.252913 916.144686 1827.856978
Aktyvi eilutė, k-1 iteracija
Aktyvi eilutė, 1 iteracija
Aktyvi eilutė, 2 iteracija Aktyvi eilutė, 3
iteracija
Aktyvi eilutė, k-2 iteracija
Aktyvi eilutė, k iteracija
Aktyvi eilutė, n-2 iteracija Aktyvi eilutė, n-1
iteracija
Pirmas procesas Antras procesas p-asis procesas
33
3.6 a)-e) paveikslėliuose pateiktose diagramose parodyti Gauso ciklinio duomenų pasiskirstymo
algoritmo vykdymo laikai.
a)
Algoritmo vykdymo laikas, kai matricos dydis 100×100
0
0.5
1
1.5
2
2.5
3
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
b)
Algoritmo vykdymo laikas, kai matricos dydis 1000×1000
0
20
40
60
80
100
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
c)
Algoritmo vykdymo laikas, kai matricos dydis 2000×2000
0
50
100
150
200
250
300
350
400
450
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
d)
Algoritmo vykdymo laikas, kai matricos dydis 4000×4000
0
100
200
300
400
500
600
700
800
900
1000
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
e)
Algoritmo vykdymo laikas, kai matricos dydis 6000×6000
0
1000
2000
3000
4000
5000
6000
7000
8000
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
3.6 pav. Gauso ciklinio duomenų pasiskirstymo algoritmo vykdymo laikas.
Lyginant su ankstesnių eksperimentų rezultatais, šio algoritmo vykdymo laikai yra prastesni.
Tačiau lyginant Gauso ciklinio duomenų pasiskirstymo lygiagretųjį algoritmą su nuosekliuoju,
stebimas žymus vykdymo laiko sumažėjimas. Galima tvirtinti, jog lygiagretusis algoritmas yra žymiai
pranašesnis už nuoseklųjį.
34
3.3. Algoritmų efektyvumo analizė
3.3.1. Lygiagretusis Jakobio iteracinio metodo algoritmas
Reikia įvertinti trijų veiksnių kaštus – skaičiavimo, duomenų perdavimo ir globalios paklaidos
radimo. Tegu kiekvienas procesas p apskaičiuos m=n/p kiekį x komponenčių. Tada kiekviena iteracija
susidės iš žingsnių:
1 žingsnis. Kiekvienam procesui apskaičiuoti m komponenčių x vienoje iteracijoje.
2 žingsnis. Kiekvienas procesas p persiunčia visiems kitiems m kiekį vektoriaus x apskaičiuotų
komponenčių ir patikrinama bus sustojimo sąlyga.
Kadangi paklaidos apskaičiavimui reikalinga nedaug operacijų, tai algoritmo efektyvume galima
į šias operacijas neatsižvelgti, dėl:
- komponentų apskaičiavimai lygiagretinami, jei imama visa lygties forma;
- jei imama ne maksimali lygties forma, tai lygiagretinasi didžiausia dalis paklaidos
apskaičiavimo.
Paklaidos apskaičiavimai mažai įtakoja pagreitėjimo koeficiento dydžiui. Be to, kadangi
paklaidos skaičiavimo kaina pakankamai maža, tai vertinant lygiagrečių iteracinių procedūrų
efektyvumą reikia įvertinti lygiagretumo išlaidas, kaip sujungimo tarp procesorių kaina bei duomenų
keitimosi laikas.[5]
Lygiagrečiojo Jakobio iteracinio metodo skaičiavimo sąnaudos yra[1]
2
1
( 1)nt
p-
=
Čia: n – matricos dydis;
p – procesų kiekis.
Algoritmo skaičiavimo laikas yra
2
1
( 1)nT
pg-
=
Čia: γ – vienos aritmetinės operacijos vykdymo laikas.
Tada Jakobio metodo algoritmo procesoriaus p skaičiavimo laikas bus[1]
(2 1)p
nT n
pg= -
Tarkime, jog kiekvienas procesorius tuo pačiu metu gali atlikti skaičiavimus ir perduoti
pranešimą kitiems procesoriams.
(3.3.1)
(3.3.2)
(3.3.3)
35
Tada vieno m ilgio pranešimo laikas bus[1]
comT ma b= +
Čia: α – starto laikas;
β – duomenų perdavimo linijos plotis;
Jeigu duomenų keitimuisi naudojamas tiesioginis duomenų perdavimo būdas, tai pasikeitimui
duomenimis reikės 0.5p(р-1) ne tuo pačiu metu nustatomu sesijų, kurių metu bus perduota ( 1)n
pp
-
duomenų. Tokiu būdu realizavimo laikas su duomenų persiuntimo išlaidomis lygiagrečiam Jakobio
algoritmui bus:[4]
(2 1) 0.5 ( 1) ( 1)p com
n nT n p p T p
p pg a= - + - + -
Čia: γ – vienos aritmetinės operacijos vykdymo laikas;
α – starto laikas;
Tcom – vieno m ilgio pranešimo laikas.
Iš algoritmo galima pastebėti, jog kiekvienos iteracijos realizacija baigiasi surinkus visus
duomenis iš visų procesorių. Tik tada yra patikrinama sąlyga ir pereinama prie sekančios realizacijos.
Iš čia gauname k-osios iteracijos uždelsimo laiką (žr. 3.3.6 formulę).[4]
20.5 ( 1) ( 1)( )
(2 1) 0.5 ( 1) ( 1)
com
com
p p T np pL k p
n nn p p T p
p p
a
g a
- - -= -
- + - + -
Čia: γ – vienos aritmetinės operacijos vykdymo laikas;
α – starto laikas;
Tcom – vieno m ilgio pranešimo laikas.
Pateiktoje 4 lentelėje iš gautų eksperimento metu duomenų apskaičiuotas yra algoritmo
efektyvumo koeficientas pagal 1.2.1 ir 1.2.2 formules.
1 ;p
p
TTS =
;p
S p
pE =
Čia: T1 – nuoseklaus algoritmo vykdymo laikas;
Tp – lygiagrečiojo algoritmo vykdymo laikas.
(1.2.2)
(3.3.4)
(3.3.5)
(3.3.6)
(1.2.1)
36
Lentelė 3. Jakobio metodo algoritmo efektyvumo koeficientai. Matricos dydis (n) Efektyvumo
koeficientas 100×100 1000×1000 2000×2000 4000×4000 6000×6000
E2 0.159968 0.132236 0.101498 0.171805 0.551143
E4 0.122702 0.031531 0.019921 0.038390 0.180525
E6 0.033647 0.016840 0.012222 0.019538 0.078734
E8 0.005374 0.012597 0.008850 0.015814 0.063461
E10 0.001005 0.005600 0.004891 0.020078 0.106086
E12 0.000709 0.004120 0.004608 0.017617 0.105931
E14 0.000702 0.003178 0.004026 0.012508 0.082379
3.7 paveikslėlyje pateikti iteracinio Jakobio metodo algoritmo efektyvumo koeficientų grafikai.
0.00
0.10
0.20
0.30
0.40
0.50
0.60
2 4 6 8 10 12 14
p
Ep
100×100 1000×1000 2000×2000 4000×4000 6000×6000
3.7 pav. Jakobio metodo algoritmo efektyvumo koeficientų grafikas.
Algoritmo efektyvumas yra labai mažas. Paskirstymui liko nepanaudota didesnė dalis
lygiagrečiojo kompiuterio pajėgumo. Algoritmas nėra labai efektyvus mažoms tiesinių lygčių
sistemos. Didesnėms matricos dydžiams pastebimas algoritmo efektyvumo padidėjimas. Lyginant
nuosekliojo ir lygiagrečiojo algoritmų vykdymo laikus bei efektyvumą, galima teigti, jog lygiagretusis
algoritmas yra efektyvus tik didelėms tiesinių lygčių sistemoms, kaip rodo eksperimentas, vykdymo
laikas realizuojant lygiagretųjį algoritmą sumažėjo tik kai matricos dydis pasiekė 6000. Tai parodo ir
3.7 paveiksle pateiktas grafikas.
37
3.3.2. Lygiagretusis blokinio duomenų paskirstymo Gauso metodo algoritmas
Tegul n dalijasi iš p. Kiekvienam procesoriui paskirta po n
mp
= matricos stulpelių Tada visuose
algoritmo žingsniuose ilgiausiai skaičiuoja paskutinis procesorius, taigi užtenka įvertinti tik jo
skaičiavimo laiką: [1]
2 2
1 1 1 1
2 2
( ( 1) ( 1) ) ( )
(3 3 1)6
n m n n m
pk k n m k m k
T m n k n k m k k
m n m n
g g
g
=
= = - + = + =
= - + + - + = + =
- + +=
å å å å
Panaudoję nuosekliojo Gauso algoritmo vykdymo laiko įverčiu (žr. 3.3.7 formulę) galima
apskaičiuoti lygiagrečiojo algoritmo spartinimo ir efektyvumo koeficientus[1]
2
2 2
(2 3 1)(3 3 1)p
n n nS
m n m n+ +
=- + +
2
2 2
(2 3 1)(3 3 1)
pp
S n nE
p n m n+ +
= =- + +
Įvertinkime ir duomenų perdavimo kaštus. Tegul P(k) žymi laiko momentą, kada buvo baigta
užduotis Tk,k+1, o F(k) laiko momentą, kada kitiems procesoriams jau buvo nusiųstas modifikuotas
k+1-asis matricos stulpelis ti,k+1.
Pirmasis lygiagrečiojo Gauso algoritmo žingsnis – kai nulinis procesorius apskaičiuoja užduotį
T1,2, nusiunčia antrąjį stulpelį t1,2 kitiems procesoriams ir užbaigia vykdyti likusias m-1 jam paskirtas
šio žingsnio užduotis. Taigi gaunami tokie laikai
(1) , (1) (1) ( 1)P n F P ng a b= = + + -
Čia: α – starto laikas;
β – duomenų perdavimo linijos plotis;
γ – vienos aritmetinės operacijos vykdymo laikas.
Kiti procesoriai pirmajame žingsnyje apskaičiuoja po m užduočių ir pereina prie antrojo
algoritmo žingsnio. Šiam etapui jie būna pasirengę laiko momentu (žr. 3.3.11 formulę) [1]
(1)T mng=
Jeigu iki to laiko dar neatėjo pranešimas iš nulinio procesoriaus, tai kiti procesoriai negali tęsti
skaičiavimų ir turi laukti pranešimo. Sąlyga, kad pabaigus pirmojo žingsnio užduotis, jau gautas
pranešimas su t1,2 stulpeliu išreiškiama nelygybe (žr. 3.3.12 formulę), kuri tenkinama, kai
( 1) ( 1)n m na b g+ - £ -
Pažymėkime k-ojo žingsnio laukimo laiką L(k), tada
(1) max(0, ( 1) ( 1) )L n m na b g= + - - -
(3.3.7)
(3.3.8)
(3.3.9)
(3.3.10)
(3.3.11)
(3.3.12)
(3.3.13)
38
Kai užduotys paskirstytos blokiniu būdu, tai ir kituose m-1 algoritmo žingsniuose nulinis
procesorius vykdo užduotis Tk,k+i ir nusiunčia modifikuotus ti,k+1 stulpelius kitiems procesoriams.
Atlikę nesudėtingus skaičiavimus, gaunami algoritmo realizacijos laikai (žr. 3.3.14 ir 3.3.15
formules)[1]
1
1
( ) ( 1)( 1) ( 1)
( 2) (2 1)( 1) ( 1)( 1)
2 6
j
k
P j m k n k n j
m n j j jj m n
g
g
-
=
æ ö= - + - + + - + =ç ÷
è ø+ + -æ ö= - + + - +ç ÷
è ø
å
( ) ( ) ( )F j P j n ja b= + + -
Jeigu išpildyta 3.3.12 sąlyga, tai nesunku pastebėti, kad ir kituose žingsniuose procesoriams
netenka laukti pranešimo su modifikuotu pagrindiniu stulpeliu ti,k+1. Dabar nagrinėkime atvejį, kai
pirmojo žingsnio laukimo laikas L(1)>0. Tada antrąjį žingsnį kiti procesoriai užbaigia laiko momentu
(žr. 3.3.16 formulę) [1]
(2) (1) ( 1) ( ( 1) ) ( 1)T F m n n m m ng g a b= + - = + - + + -
Iš 3.3.15 lygybės gauname, kad stulpelis ti,3 nusiunčiamas laiko momentu[1]
(2) ( 2)F mn ng a b= + + -
taigi F(2)<T(2), todėl L(2)=0 ir procesoriams nereikia laukti pranešimo. Nesunku įsitikinti, kad
ši išvada yra teisinga ir kituose žingsniuose 3≤ j ≤ m.
Algoritmo m+1-ajame žingsnyje situacija vėl kartojasi. Pirmojo procesoriaus persiųsto
pranešimo kiti procesoriai laukia L(m+1) sekundžių (žr. 3.3.18 formulę) [1]
( 1) ( 1) ( 1)( )L m n m m n ma b g+ = + - - - - -
Kituose žingsniuose 3≤ j ≤ m laukimo laikas L(2)=0. Todėl lygiagrečiojo Gauso algoritmo esant
blokiniam užduočių paskirstymui visa pranešimo laukimo trukmė yra (žr. 3.3.19 formulę) [1]
2
0
( ( 1) ( 1)( ))
(2 ( 2 2) ( 1)( 2 ))2
p
pk
L n km m n km
n mn m m n m
m
a b g
a b g
=
=
= + - - - - - =
-= + + - - - +
å
Taigi bendras uždavinio sprendimo laikas yra (žr. 3.3.20 formulę) [1]
2 2
(2 ( 2 2) ( 1)( 2 ))2
(3 3 1)6
p
n mT n m m n m
mm n m n
a b g
g
-= + + - - - + +
- + ++
Čia: α – starto laikas;
β – duomenų perdavimo linijos plotis;
γ – vienos aritmetinės operacijos vykdymo laikas.
(3.3.14)
(3.3.15)
(3.3.16)
(3.3.17)
(3.3.18)
(3.3.19)
(3.3.20)
39
5 lentelėje pateikti lygiagrečiojo Gauso algoritmo efektyvumo koeficientai, kurie apskaičiuoti iš
eksperimento metu gautų duomenų.
Lentelė 4. Gauso metodo algoritmo efektyvumo koeficientai. Matricos dydis (n) Efektyvumo
koeficientas 100×100 1000×1000 2000×2000 4000×4000 6000×6000
E2 0.112638 0.514303 0.678454 0.772013 0.805422
E4 0.029405 0.229839 0.383524 0.526508 0.561411
E6 0.010969 0.129867 0.240359 0.378436 0.479661
E8 0.007525 0.083508 0.127659 0.295301 0.380822
E10 0.005477 0.065199 0.011419 0.065613 0.136247
E12 0.003238 0.048950 0.006016 0.032810 0.066729
E14 0.002312 0.031983 0.004340 0.025180 0.040471
Vaizdžiai pamatyti efektyvumo koeficientus galima 3.8 paveikslėlyje pateiktame grafike.
0.00
0.10
0.20
0.30
0.40
0.50
0.60
0.70
0.80
0.90
2 4 6 8 10 12 14
p
Ep
100×100 1000×1000 2000×2000 4000×4000 6000×6000
3.8 pav. Gauso metodo algoritmo efektyvumo koeficientų grafikas.
Algoritmas nėra labai efektyvus, nes po m žingsnių pirmasis procesorius baigia darbą, dar po m
žingsnių darbą baigia antrasis procesorius ir taip toliau. Pasirenkant blokinio pasiskirstymo metodą
reikia atsižvelgti į duomenų perdavimo kaštus. Didinant procesų skaičių, perdavimo kaštai irgi didėja,
tuo pačiu metu mažėja algoritmo efektyvumas. Tikslinga yra parinkti tinkamą bloko m dydį taip, kad
duomenų perdavimo kaštai nebūtų didesnį už skaičiavimo kaštus.
Suradus Tp išvestinę pagal dydį p ir prilyginus nuliui, galima apskaičiuoti optimalų bloko dydį m.
Gauname lygtį (žr. 3.3.21 formulę) [1]
40
22
2( ) 0
2pdT n
mdp m
g g b= - - =
Taigi optimalus bloko ilgis yra (žr. 3.3.22 formulę) [1]
1 /m b g= +
Čia: α – starto laikas;
β – duomenų perdavimo linijos plotis;
γ – vienos aritmetinės operacijos vykdymo laikas.
3.3.3. Lygiagretusis ciklinio duomenų paskirstymo Gauso metodo algoritmas
Po p algoritmo žingsnių kiekvieno procesoriaus turimų stulpelių skaičius sumažės vienetu ir
beveik visą algoritmo realizavimo laiką užduotys yra tolygiai paskirstytos visiems procesoriams.
Lygiagrečiojo algoritmo skaičiavimo laikas yra (žr. 3.3.23 formulę) [1]
1 1
( 1)(4 3 )( 1) ( ( 1) 1)
12
pm
pk j
n m n pT m k n k p jg g
= =
+ + -= - + - - - + =å å
Čia: n
mp
= ;
γ – vienos aritmetinės operacijos vykdymo laikas.
Dabar jau galima apskaičiuoti lygiagrečiojo algoritmo spartinimo ir efektyvumo koeficientus (žr.
3.3.24 ir 3.3.25 formules) [1]
( 1)(2 1)( 1)(2 1.5 2)p
n nS
m n p+ +
=+ + -
( 1)(2 1)( )(2 1.5 2)
pp
S n nE
p n p n p+ +
= =+ + -
Palyginę naujus ir blokinio duomenų paskirstymo rezultatus, matome, kad ciklinis duomenų
paskirstymas yra efektyvesnis. Tai patvirtina ir asimptotinė analizė, kai fiksuojame procesorių skaičių
p ir didiname matricos dydį n. Tada gaunamas toks asimptotinis lygiagrečiojo Gauso algoritmo
efektyvumo koeficiento įvertis
lim 1pnE
®¥=
Tačiau šioje analizėje neatsižvelgta į duomenų persiuntimo kaštus. Kai šie kaštai nėra maži,
blokinis duomenų paskirstymas gali būti ir efektyvesnis už ciklinį duomenų paskirstymą.
Esant cikliniam užduočių paskirstymui kiekviename algoritmo žingsnyje pagrindinio stulpelio
siuntėjas yra vis kitas procesorius. Todėl, kai tik bloko dydis yra mažesnis už m, apibrėžtą 3.3.12
nelygybėje, procesoriai turi laukti pranešimo. Kai kuriems uždaviniams ciklinio užduočių skirstymo
(3.3.24)
(3.3.25)
(3.3.23)
(3.3.26)
(3.3.21)
(3.3.22)
41
skaičiavimo laiko sumažėjimas gali būti mažesnis už duomenų perdavimo kaštų padidėjimą ir
efektyvesnis bus blokinis algoritmas. Todėl ir yra svarbu iš anksto įvertinti įvairių duomenų
paskirstymų sąnaudas.[1]
6 lentelėje pateikti lygiagrečiojo Gauso algoritmo efektyvumo koeficientai, kurie apskaičiuoti iš
eksperimento metu gautų duomenų.
Lentelė 6. Gauso metodo algoritmo efektyvumo koeficientai. Matricos dydis (n) Efektyvumo
koeficientas 100×100 1000×1000 2000×2000 4000×4000 6000×6000
E2 0.035805 0.557201 0.742438 0.948313 0.907619
E4 0.003150 0.105380 0.121846 0.821792 0.880455
E6 0.000508 0.051145 0.067194 0.684139 0.834973
E8 0.000303 0.020505 0.044193 0.429904 0.796172
E10 0.000174 0.014700 0.009101 0.118314 0.496794
E12 0.000135 0.010166 0.007209 0.090709 0.295788
E14 0.000116 0.003093 0.005120 0.045295 0.287766
3.9 paveikslėlyje pateiktas lygiagrečiojo Gauso algoritmo su cikliniu duomenų paskirstymu
efektyvumo koeficiento grafikas.
0.00
0.10
0.20
0.30
0.40
0.50
0.60
0.70
0.80
0.90
1.00
2 4 6 8 10 12 14
p
Ep
100×100 1000×1000 2000×2000 4000×4000 6000×6000
3.9 pav. Gauso metodo algoritmo efektyvumo koeficientų grafikas.
Lyginant blokinio bei ciklinio duomenų paskirstymo algoritmus pastebimas ciklinio algoritmo
pranašumas. Analizuojant 3.9 paveiksle pateiktą grafiką, matome geresnius algoritmo rezultatus.
Tačiau ciklinio duomenų paskirstymo algoritmas turi didesnius duomenų perdavimo kaštus ir didelėms
tiesinių lygčių sistemoms blokinis duomenų perdavimas yra efektyvesnis.
42
3.3.4. Rezultatų, gautų eksperimentų metu, vertinimas
Visi eksperimentai buvo vykdomi MIF klasteryje, kuris veikia 100 Mb/s tinkle. Skirtingai nuo
nuosekliojo algoritmo, lygiagrečiųjų algoritmo analizės metu reikia įvertinti tiek skaičiavimo kaštus,
tiek duomenų perdavimo kaštus. Eksperimento rezultatai rodo, jog mažoms tiesinių lygčių sistemoms
lygiagretieji algoritmai nėra efektyvus. Vykdymo laiko sumažėjimas matomas didesniems matricų
dydžiams bei parinkus optimalų procesų kiekį. Kaip matoma iš 3.4, 3.5 ir 3.6 paveikslėlių
lygiagrečiojo algoritmo vykdymo laikas yra geresnis už nuosekliojo algoritmo, kai matricų dydžiai yra
pakankamai dideli, o parinkus per daug procesų, vykdymo laikas didėja, nes mažėjant užduoties
dydžiui skaičiavimo kaštai yra maži palyginus su duomenų perdavimo kaštais. Taigi dideliems
uždaviniams aiškiai galima matyti lygiagrečiųjų algoritmų pranašumą.
Realizuojant tiesinių lygčių sistemų sprendimo metodus buvo parinkti tris populiariausi
lygiagretieji algoritmai: Iteracinis Jakobio metodo algoritmas, Gauso metodo algoritmai su blokinio
bei ciklinio duomenų pasiskirstymo būdais. 3.10 paveiksle pateiktoje diagramoje pavaizduoti
algoritmo vykdymo laikas su skirtingais procesų kiekiais ir matricos dydžiu n=6000.
0
1000
2000
3000
4000
5000
6000
7000
8000
1 2 4 6 8 10 12 14
Procesų kiekis
Lai
kas,
sek
Jakobio alg. Blokinis alg. Ciklinis alg.
3.10 pav. Parinktų algoritmų vykdymo laikai, kai matricos dydis n=6000
Pateiktoje diagramoje matome, jog geriausius rezultatus rodo Jakobio metodą realizuojantis
algoritmas, o blogiausius Gauso metodą su cikliniu duomenų pasiskirstymų realizuojantis algoritmas.
Tačiau lyginant su nuosekliuoju algoritmu Gauso metodą su cikliniu duomenų pasiskirstymų
realizuojantis lygiagretus algoritmas yra efektyviausias, kadangi vykdymo laikas žymiai sumažėjo. Tai
galima stebėti ir algoritmo efektyvumo koeficientų grafiko (žr. 3.11 pav.)
43
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
2 4 6 8 10 12 14
Procesų kiekis
Ep
Jakobio alg. Blokinis alg. Ciklinis alg.
3.11 pav. Parinktų algoritmų efektyvumo koeficientai, kai matricos dydis n=6000
Lyginant parinktus lygiagrečiuosius algoritmus galima išvardinti sekančius privalumus ir
trūkumus.
Iteracinio Jakobio metodo algoritmo privalumai:
- algoritmo vykdymo laikas yra geriausias iš pasirinktų algoritmų,
- tinkamas didelioms tiesinių lygčių sistemoms, kadangi nereikalauja laikyti atmintyje
visos sistemos koeficientų matricos ir algoritmo efektyvumas didesnėms matricoms
didėja,
- skaičiavimų paklaidos nesikaupia, nes kiekvienos esamos iteracijos rezultatas nepriklauso
nuo ankstesnių iteracijų skaičiavimų;
trūkumai:
- tiesinių lygčių sistema turi tenkinti konvergavimo sąlygas,
- algoritmo efektyvumas yra mažiausias.
Tiesinio Gauso metodo algoritmo su blokinio duomenų pasiskirstymu privalumai:
- turi mažiausius duomenų perdavimo kaštus, kadangi reikalauja mažiau sujungimų,
- tinkamas didesnei tiesinių lygčių sistemų klasei,
- lygiagretusis algoritmas yra pakankamai efektyvus ir mažesniems tiesinių lygčių
sistemoms;
trūkumai:
- reikalauja saugoti atmintyje iškarto visą matricą, o dideliems n dydžiams sunaudojama
daug atminties,
44
- paklaidos skaičiavimo procese kaupiasi, nes apskaičiavimai esamos operacijos reikalauja
ankstesnių operacijų rezultatų.
Tiesinio Gauso metodo algoritmo su blokinio duomenų pasiskirstymu privalumai:
- lygiagretusis algoritmas yra efektyvus palyginus su pasirinktais algoritmais,
- tinka didesnei tiesinių lygčių sistemų klasei;
trūkumai:
- reikalauja saugoti atmintyje iškarto visą matricą, o dideliems n sunaudojama daug
atminties,
- paklaidos skaičiavimo procese kaupiasi, nes apskaičiavimai esamos operacijos reikalauja
ankstesnių operacijų rezultatų,
- algoritmo vykdymo laikas yra didžiausias iš pasirinktų algoritmų.
45
4. IŠVADOS
Darbe buvo išanalizuoti keli klasikiniai tiesinių lygčių sistemų sprendimo metodai ir juos
realizuojantys lygiagretūs algoritmai. Eksperimentų metu ištirtas jų veikimas kompiuterių tinkle bei
padarytos tokios išvados:
· iš parinktų algoritmų geriausius vykdymo laikus parodė iteracinis Jakobio algoritmas.
Gauso metodo algoritmas esant blokiniam duomenų paskirstymui to pačio dydžio užduotį
išsprendė dvigubai lėčiau, o esant cikliniam duomenų paskirstymui vykdymo laikas yra
kelis kart didesnis;
· lyginant su nuosekliais algoritmais, iteracinio Jakobio metodo lygiagretusis algoritmas
turi mažiausią efektyvumą. Mažoms tiesinių lygčių sistemoms lygiagretaus algoritmo
vykdymo laikas nėra mažesnis už nuosekliojo algoritmo vykdymo laiką. Realizuojant
Gauso metodo lygiagrečiuosius algoritmus esant tiek blokiniam tiek cikliniam duomenų
pasiskirstymui vykdymo laikas sumažėjo atliekant užduotį su tiesinių lygčių n=1000
dydžio sistema;
· didelėms tiesinių lygčių sistemoms iteracinis Jakobio metodas yra geriausias, kadangi,
skirtingai nei tiesinis Gauso metodas, jis nereikalauja laikyti atmintyje visos matricos ir
dideliems uždaviniams iteracinio Jakobio algoritmo efektyvumas yra didesnis bei
vykdymo laikas mažiausias;
· lyginant iteracinius ir tiesinius metodus, tiesiniai metodai tinka didesnei tiesinių lygčių
sistemų klasei. Tam, kad iteracinis Jakobio metodas konverguotų, turi būti tenkinamos
konvergavimo sąlygos, o tiesinis Gauso metodas tiesinių lygčių sistemoms papildomų
sąlygų neturi;
· net ir esant dideliems matricų dydžiams parinkus per daug procesų, vykdymo laikas
didėja, nes mažėjant užduoties dydžiui skaičiavimo kaštai yra maži palyginus su
duomenų perdavimo kaštais. Tikslinga parinkti optimalų procesorių kiekį siekiant
geriausio algoritmo vykdymo laiko;
· neatsižvelgiant į duomenų perdavimo kaštus palyginę ciklinio ir blokinio duomenų
paskirstymo rezultatus, ciklinis duomenų paskirstymas yra efektyvesnis. Tai patvirtina ir
asimptotinė analizė, kai fiksuojamas procesorių skaičius p ir didinamas matricos dydis n;
46
· kai duomenų persiuntimo kaštai nėra maži, blokinis duomenų paskirstymas yra
efektyvesnis už ciklinį duomenų paskirstymą. Esant cikliniam užduočių paskirstymui
kiekviename algoritmo žingsnyje pagrindinio stulpelio siuntėjas yra vis kitas procesorius.
Todėl, kai tik bloko dydis yra mažas, procesoriai turi laukti pranešimo. Kai kuriems
uždaviniams ciklinio užduočių skirstymo skaičiavimo laiko sumažėjimas gali būti
mažesnis už duomenų perdavimo kaštų padidėjimą ir efektyvesnis yra blokinis
algoritmas;
· skirtingai nuo iteracinių metodų, dideliu tiesinių metodų trūkumu yra paklaidos
skaičiavimo procese, nes esamos operacijos apskaičiavimai reikalauja ankstesnių
operacijų rezultatų, o iteracinių metodų skaičiavimų paklaidos nesikaupia, nes kiekvienos
esamos iteracijos rezultatas nepriklauso nuo ankstesnių iteracijų skaičiavimų.
47
5. SANTRAUKA
Šiame darbe buvo apžvelgti pagrindiniai tiesinės algebros uždaviniai – tiesinių lygčių sistemų
sprendimai. Aptarti tiesinių lygčių sistemų sprendimo metodai bei jų lygiagretieji algoritmai.
Pasirinkus lygiagrečius algoritmus, kompiuterių tinkle buvo atlikti eksperimentai su skirtingais
procesorių ir procesų kiekiais bei įvairių matricų dydžiais, kurių metu buvo siekiama palyginti juos
tarpusavyje ir su nuosekliais algoritmais bei nustatyti algoritmų efektyvumą.
Su eksperimentų metu gautais duomenimis atlikta lygiagrečiųjų algoritmų efektyvumo analizė.
Rezultatai parodė sprendimo radimo laiko sumažėjimą realizuojant lygiagrečiuosius algoritmus. Taip
pat buvo išvardinti tiesinių lygčių sprendimo metodų ir jų lygiagrečiųjų algoritmų privalumai ir
trūkumai.
6. SUMMARY
Parallel Algorithm for Solving of Linear Equations Systems
In this master paper the main propositions of linear algebra and derivations of linear equations
systems were passed in review.
The experiments with different quantity of processors and processes, and a variety of matrices
sizes were completed by choosing parallel algorithms in a network of computers. The aims of this
experiment were to compare parallel algorithms with each other and with sequantial algorithms, and to
ascertain the algorithms efficiency.
On the basis of the results of experiments, the analysis of parallel algorithms was done. The
results revealed the reduction of time while finding a derivation by realising parallel algorithms. In
addition, advantages and disadvantages of derivation methods of linear equations and parallel
algorithms were named.
48
7. LITERATŪRA
[1] Čiegis R. Lygiagretieji algoritmai. Vilnius „Technika“ 2001.
[2] Vilkas R. Jakobio ir Zeidelio metodai. 2009
[3] Антонов А. С. Введение в параллельные вычисления. Методическое пособие.
Moсква 2002
[4] Воеводин В. В. Воеводин Вл. В. Параллельные вычисления. БХВ-Петербург 2002
[5] Шпаковский Г. И., Серикова Н. В. Программирование для многопроцессорных
систем в стандарте MPI. Mинск БГУ 2002
[6] Старченко А. В. Высокопроизводительные вычисления на кластерах. Учебное
пособие. Издательство Томского университета 2008
[7] Kорнеев В. Д. Параллельное программирование в MPI. Новосибирск 2002
[8] Васченко Г. В. Вычислительная математика. Kрасноярск 2005.
[9] Тюканов А. С. Нелинейные уравнения с одним неизвестным
http://physics.herzen.spb.ru/library/01/01/nm_labs/linear_eq.htm [žiūrėta 2010-04-15]
[10] Newelski L. Układy równań liniowych
http://www.math.uni.wroc.pl/~newelski/dydaktyka/alglin2A/skrypt2/skrypt/node10.html [žiūrėta
2011-04-08]
[11] Belovas I. Tiesinių lygčių sistemos lygiagrečiuose algoritmuose
http://olgal.home.mruni.eu/wp-content/uploads/2008/09/mt_10_lygciu_sistemos.ppt [žiūrėta
2010-04-17]
[12] Lukoševičiūtė K. Lygiagretieji skaičiavimai
http://kopustas.elen.ktu.lt/studentai/_media/lygiagretieji_sk.ppt [žiūrėta 2010-04-17]
[13] Igumenov A. Lygiagrečių skaičiavimų tyrimas dideliuose kompiuterių tinkluose.
Magistrinis darbas. 2007 m.
[14] Морев Н. В. Решение СЛАУ с использованием кластерной системы. ВЛГУ 2005
[15] Belovas I. Matematinė analizė ir tiesinė algebra
http://www.mruni.lt/mru_lt_dokumentai/katedros/informatikos_ir_statistikos_katedra/Paskaitu_
medziaga/Matematine_analize_ir_tiesine_algebra/mt_12-13.ppt [žiūrėta 2010-04-15]
[16] Kosareva N. Paskaitos http://e-stud.vgtu.lt/files/dest/5003/paskaitos.pdf [žiūrėta 2010-10-
08]
[17] Букатов А. А., Дацюк Б. Н., Жегуло А. И. Программирование многопроцессорных
вычислительных систем. Ростов-на-Дону 2003
49
8. PRIEDAS
1 priedas. Iteracinis Jakobio metodo lygiagretusis algoritmas
#include <stdafx.h> #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h> #include <math.h> #include "mpi.h"
int Myid; int ProcNum;
// Jacobio metodo realizacija
void Jacobi (int pRows, int Size, double *pXold, int *pPE, double *pVector, double *pMatrix, double *pX)
{ int i, j; double sum; sum=0; for (i=0; i<pRows; i++) { sum=0; //naujosios iteracijos X vektoriaus skaičiavimas (žr.2.2.7 formulę) for (j=0; j<(pPE[Myid]+i); j++) { sum+=pMatrix[(pPE[Myid]+i)*Size+j]*pXold[j]; } for (j=(pPE[Myid]+i)+1; j<Size; j++) { sum+=pMatrix[(pPE[Myid]+i)*Size+j]*pXold[j]; } pX[(pPE[Myid]+i)]=(pVector[(pPE[Myid]+i)]-
sum)/pMatrix[(pPE[Myid]+i)*Size+(pPE[Myid]+i)]; } }
// Atsitiktinių matricos ir vektoriaus reikšmių generavimo funkcija
void RandomDataInitialization (double* pMatrix, double* pVector, int Size) { int i, j; int suma; for (i=0; i<Size; i++) { suma=0; pVector[i] = rand()%90; for (j=0; j<Size; j++) { if (i==j) pMatrix[i*Size+j] = (rand()%Size)+Size*10; else pMatrix[i*Size+j] = rand()%10;
50
} } }
// Funkcija skirta vektoriaus išvedimui
void PrintVector (double* pVector, int Size) { int i; for (i=0; i<Size; i++) printf("Vektorius %7.4f ", pVector[i]); }
// Funkcija skirta matricos išvedimui
void PrintMatrix (double* pMatrix, int RowCount, int ColCount) { int i, j; for (i=0; i<RowCount; i++) { for (j=0; j<ColCount; j++) printf("Sistemos matrica: %7.4f ", pMatrix[i*ColCount+j]); printf("\n"); } }
//Pagrindinė programa
void main (int argc, char* argv[]) { double* pMatrix; // TLS matrica double* pVector; // Desine TLS dalis laisvieji nariai double* pX; // Vektorius-rezultatas k-ojoje iteracijoje double* pXnew; // Vektorius-rezultatas k+1-joje iteracijoje double* pXold; // Vektorius-rezultatas double *pProcRows; // Eiluciu skaicius matricos A, vienam procesui double *pProcVector; // Vektoriaus b blokai vienam procesui double *pProcX; // Vektoriaus x blokai vienam procesui int Size; // Matricos ir vektoriaus dydis int RowNum; // Eiluciu skaicius vienam procesui double Error = 0.00000001; //paklaidos dydis double pNorm=0, pPak; int Result; double start, finish, duration;
setvbuf(stdout, 0, _IONBF, 0);
MPI_Init ( &argc, &argv ); MPI_Comm_rank ( MPI_COMM_WORLD, &Myid ); MPI_Comm_size ( MPI_COMM_WORLD, &ProcNum ); //Matricos dydžio nuskaitymas if (Myid == 0) { do { printf("Įveskit matricos ir vektoriaus dydį: "); scanf("%d", &Size);
51
if (Size < ProcNum) {printf("Skaičius turi buti didesnis už procesu skaičių! \n");}
} while (Size < ProcNum); }
//Matricos dydžio bei paklaidos procesams persiuntimas
MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&Error, 1, MPI_INT, 0, MPI_COMM_WORLD);
// Atminties išskyrimas ir pradiniu duomenų priskyrimas
pMatrix = new double [Size*Size]; pVector = new double [Size]; pX = new double [Size]; if (Myid == 0) { RandomDataInitialization(pMatrix, pVector, Size); } start = MPI_Wtime();
// Matricos ir vektoriaus procesams nusiuntimas
MPI_Bcast(pVector, Size, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(pMatrix, Size*Size, MPI_DOUBLE, 0, MPI_COMM_WORLD); pXnew = new double [Size]; if (Myid==0) { PrintMatrix(pMatrix, Size, Size); PrintVector(pVector, Size); }
//Duomenų kiekio apskaičiavimas kiekvienam procesui
RowNum = Size/ProcNum +(Size%ProcNum>Myid?1:0);
// Atminties išskyrimas laikiniems objektams
int *pProcNum; int *pProcInd; pProcRows = new double [RowNum*Size]; pSendInd = new int [ProcNum]; pSendNum = new int [ProcNum]; pProcVector = new double [RowNum]; pProcInd = new int [ProcNum]; pProcNum = new int [ProcNum];
pProcX = new double [RowNum];
//Duomenų pasiskirstymas
int *pSendNum; // Elementų siunčiamų procesui skaičius int *pSendInd; // Siunčiamų procesui elementų, pirmo elemento indeksas int i;
// Matricų eilučių išdėstymo nustatymas duotajam procesui
pSendNum[0] = RowNum*Size; pSendInd[0] = 0; for (i=1; i<ProcNum; i++)
52
{ pSendNum[i] = RowNum*Size; pSendInd[i] = pSendInd[i-1]+pSendNum[i-1]; }
// Eilučių ir matricos laisvųjų narių pasiskirstymas
pProcInd[0] = 0; pProcNum[0] = Size/ProcNum +(Size%ProcNum>0?1:0); for (i=1; i<ProcNum; i++) { pProcNum[i] = Size/ProcNum +(Size%ProcNum>i?1:0); pProcInd[i] = pProcInd[i-1]+pProcNum[i-1]; }
//Vektoriaus X generavimas ir persiuntimas procesams
if (Myid == 0){ for (i=0; i<Size; i++) { pX[i]= 0;//pVector[i]/pMatrix[i*Size+i]; } } MPI_Bcast(pX, Size, MPI_DOUBLE, 0, MPI_COMM_WORLD); int first; //aktyviojo proceso matricos pirmoji eilutė Xold = new double [Size]; int Iter=0; //iteracijų skaitliukas do{ Iter++; for (i=0; i<Size; i++) { pXold[i]= pX[i]; }
//kreipimasis į funkciją realizuojančia Jacobio metodą
Jacobi(RowNum, Size, pXold, pProcInd, pVector, pMatrix, pX); MPI_Allgatherv (&pX[first], RowNum, MPI_DOUBLE, pX, pProcNum, pProcInd,MPI_DOUBLE, MPI_COMM_WORLD); double pNormold; if (Myid ==0) { pNormold=pNorm; pNorm=0; for (i=0; i<Size; i++){ pPak=fabs(pX[i]-pXold[i]); if (pNorm<pPak) pNorm=pPak; } printf ("\n paklaida %f", pNorm); Result=Error<pNorm; } MPI_Bcast(&Result, 1, MPI_INT, 0, MPI_COMM_WORLD); } while (Result);
53
//Atminties išvalymas
delete [] pSendNum; delete [] pSendInd; finish = MPI_Wtime(); duration = finish-start; if (Myid == 0) {
// Nežinomųjų vektoriaus spausdinimas
printf ("\n Vektorius x lygus: \n"); PrintVector(pX, Size); }
//Sugaišto laiko išvedimas į ekraną
if (Myid == 0){ printf("\n Iteracijos: %d\n", Iter); printf("\n Sugaištas laikas: %f\n", duration);}
// Skaičiavimo proceso nutraukymas
if (Myid == 0) { delete [] pMatrix; delete [] pVector; delete [] pX; } delete [] pXold; delete [] pProcVector; delete [] pProcX; MPI_Finalize(); }
2 priedas. Gauso metodo blokinio duomenų pasiskyrstymo lygiagretusis
algoritmas
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h> #include <math.h> #include <mpi.h> int ProcNum; // Procesų skaičius int ProcRank; // Proceso eilė int *pParallelPivotPos; // Eilučių, pasirinktų apdorojimui, skaičius int *pProcPivotIter; // Iteracijų procese skaičius int* pProcInd; //Pirmos eilutės numeris, kuri atiteko procesui int* pProcNum; // Lygčių sistemos eilučių skaičius, skirtas procesui // Funkcija priskiria kanonines reikšmes matricos ir vektoriaus elementams void DummyDataInitialization (double* pMatrix, double* pVector, int Size) { int i, j; for (i=0; i<Size; i++) {
54
pVector[i] = i+1; for (j=0; j<Size; j++) { if (j <= i) pMatrix[i*Size+j] = 1; else pMatrix[i*Size+j] = 0; } } } // Atsitiktinių matricos ir vektoriaus reikšmių generavimo funkcija void RandomDataInitialization (double* pMatrix, double* pVector, int Size) { int i, j; srand(unsigned(clock())); for (i=0; i<Size; i++) { pVector[i] = rand()/double(1000); for (j=0; j<Size; j++) { if (j <= i) pMatrix[i*Size+j] = rand()/double(1000); else pMatrix[i*Size+j] = 0; } } } // Funkcija atminties išskyrimui ir duomenų inicializavimui void ProcessInitialization (double* &pMatrix, double* &pVector, double* &pResult,
double* &pProcRows, double* &pProcVector, double* &pProcResult, int &Size, int &RowNum) { int RestRows; // Eilučių skaičius, kurios dar nepanaudotos int i; if (ProcRank == 0) { do { printf("\n Įveskit matricos ir vektoriaus dydį: "); scanf("%d", &Size); if (Size < ProcNum) {printf("Skaičius turi būti didesnis už procesų skaičių! \n");} } while (Size < ProcNum); } MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD); RestRows = Size; for (i=0; i<ProcRank; i++) RestRows = RestRows-RestRows/(ProcNum-i); RowNum = RestRows/(ProcNum-ProcRank); pProcRows = new double [RowNum*Size]; pProcVector = new double [RowNum]; pProcResult = new double [RowNum]; pParallelPivotPos = new int [Size]; pProcPivotIter = new int [RowNum];
55
pProcInd = new int [ProcNum]; pProcNum = new int [ProcNum]; for (int i=0; i<RowNum; i++) pProcPivotIter[i] = -1; if (ProcRank == 0) { pMatrix = new double [Size*Size]; pVector = new double [Size]; pResult = new double [Size]; // DummyDataInitialization (pMatrix, pVector, Size); RandomDataInitialization(pMatrix, pVector, Size); } } // Duomenų tarp procesų pasiskirstymo funkcija void DataDistribution(double* pMatrix, double* pProcRows, double* pVector,
double* pProcVector, int Size, int RowNum) { int *pSendNum; // Elementų siunčiamų procesui skaičius int *pSendInd; // Siunčiamų procesui elementų, pirmo elemento indeksas int RestRows=Size; // Nepasiskirstytų dar eilučių skaičius int i; // Atminties išskyrimas laikiniems objektams pSendInd = new int [ProcNum]; pSendNum = new int [ProcNum]; // Matricų eilučių išdėstymo nustatymas duotajam procesui RowNum = (Size/ProcNum); pSendNum[0] = RowNum*Size; pSendInd[0] = 0; for (i=1; i<ProcNum; i++) { RestRows -= RowNum; RowNum = RestRows/(ProcNum-i); pSendNum[i] = RowNum*Size; pSendInd[i] = pSendInd[i-1]+pSendNum[i-1]; } // Eilučių pasiskirstymas MPI_Scatterv(pMatrix, pSendNum, pSendInd, MPI_DOUBLE, pProcRows,
pSendNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD); // Matricų eilučių išdėstymo nustatymas dabartiniam procese RestRows = Size; pProcInd[0] = 0; pProcNum[0] = Size/ProcNum; for (i=1; i<ProcNum; i++) { RestRows -= pProcNum[i-1]; pProcNum[i] = RestRows/(ProcNum-i);
56
pProcInd[i] = pProcInd[i-1]+pProcNum[i-1]; } MPI_Scatterv(pVector, pProcNum, pProcInd, MPI_DOUBLE, pProcVector, pProcNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD); // Atminties išvalimas delete [] pSendNum; delete [] pSendInd; } // Funkcija, skirta rezultatų vektoriaus surinkimui void ResultCollection(double* pProcResult, double* pResult) { //Surinkimas iš visų procesų vektoriaus-rezultato MPI_Gatherv(pProcResult, pProcNum[ProcRank], MPI_DOUBLE, pResult, pProcNum, pProcInd, MPI_DOUBLE, 0, MPI_COMM_WORLD); } // Funkcija skirta matricos išvedimui void PrintMatrix (double* pMatrix, int RowCount, int ColCount) { int i, j; for (i=0; i<RowCount; i++) { for (j=0; j<ColCount; j++) printf("%7.4f ", pMatrix[i*ColCount+j]); printf("\n"); } } // Funkcija skirta vektoriaus išvedimui void PrintVector (double* pVector, int Size) { int i; for (i=0; i<Size; i++) printf("%7.4f ", pVector[i]); } // Funkcija skirta vektoriaus-rezultato išvedimui void PrintResultVector (double* pResult, int Size) { int i; for (i=0; i<Size; i++) printf("%7.4f ", pResult[pParallelPivotPos[i]]); } // Funkcija skirta stulpelio elementams išeliminuoti void ParallelEliminateColumns(double* pProcRows, double* pProcVector, double*
pPivotRow, int Size, int RowNum, int Iter) { double multiplier; for (int i=0; i<RowNum; i++) { if (pProcPivotIter[i] == -1) { multiplier = pProcRows[i*Size+Iter] / pPivotRow[Iter]; for (int j=Iter; j<Size; j++) {pProcRows[i*Size + j] -= pPivotRow[j]*multiplier;} pProcVector[i] -= pPivotRow[Size]*multiplier;
57
} } } // Gauso išeliminavimo funkcija void ParallelGaussianElimination (double* pProcRows, double* pProcVector, int Size, int
RowNum) { double MaxValue; // Proceso aktyviojo elemento reikšme int PivotPos; // Aktyvios eilutės padėtis proceso duomenyse // Struktūra, skirta aktyvios eilutės žymėjimui struct { double MaxValue; int ProcRank; } ProcPivot, Pivot; // pPivotRow naudojamas aktyvios eilutės įsiminimui ir persiuntimams vektoriaus b elementams double* pPivotRow = new double [Size+1]; // Gauso šalinimo operacijos iteracijos for (int i=0; i<Size; i++) { // lokalios aktyvios eilutės skaičiavimas double MaxValue = 0; for (int j=0; j<RowNum; j++) { if ((pProcPivotIter[j] == -1) && (MaxValue < fabs(pProcRows[j*Size+i]))) { MaxValue = fabs(pProcRows[j*Size+i]); PivotPos = j; } } ProcPivot.MaxValue = MaxValue; ProcPivot.ProcRank = ProcRank; // Aktyvaus proceso paieška (procesas turintis didžiausia MaxValue reikšmę) MPI_Allreduce(&ProcPivot, &Pivot, 1, MPI_DOUBLE_INT, MPI_MAXLOC,
MPI_COMM_WORLD); // Aktyvios eilutės sintinėjimas if ( ProcRank == Pivot.ProcRank ) { pProcPivotIter[PivotPos]= i; //Iteracijų skaičius pParallelPivotPos[i]= pProcInd[ProcRank] + PivotPos; } MPI_Bcast(&pParallelPivotPos[i], 1, MPI_INT, Pivot.ProcRank,
MPI_COMM_WORLD); if ( ProcRank == Pivot.ProcRank ) { // Aktyvios eilutės pildymas for (int j=0; j<Size; j++) {pPivotRow[j] = pProcRows[PivotPos*Size + j];} pPivotRow[Size] = pProcVector[PivotPos]; } MPI_Bcast(pPivotRow, Size+1, MPI_DOUBLE, Pivot.ProcRank,
MPI_COMM_WORLD);
58
ParallelEliminateColumns(pProcRows, pProcVector, pPivotRow, Size, RowNum, i); } } // Funkcija skirta aktyvios eilutės paieškai, kai vykdoma algoritmo atbulinė eiga void FindBackPivotRow(int RowIndex, int Size, int &IterProcRank, int &IterPivotPos) { for (int i=0; i<ProcNum-1; i++) { if ((pProcInd[i]<=RowIndex) && (RowIndex<pProcInd[i+1])) IterProcRank = i; } if (RowIndex >= pProcInd[ProcNum-1]) IterProcRank = ProcNum-1; IterPivotPos = RowIndex - pProcInd[IterProcRank]; } // Atbulinės eigos funkcija void ParallelBackSubstitution (double* pProcRows, double* pProcVector, double* pProcResult, int Size, int RowNum) { int IterProcRank; // Proceso aktyvios eilutės rangas int IterPivotPos; // Aktyvios eilutės padėtis procese double IterResult; // Dabartinio nežinomojo suskaičiuota reikšme double val; // Atbulinės eigos iteracijos for (int i=Size-1; i>=0; i--) { // Proceso, kuris turi aktyvia eilute rango skaičiavimas FindBackPivotRow(pParallelPivotPos[i], Size, IterProcRank, IterPivotPos); // Nežinomo skaičiavimas if (ProcRank == IterProcRank) { IterResult = pProcVector[IterPivotPos]/pProcRows[IterPivotPos*Size+i]; pProcResult[IterPivotPos] = IterResult; } // Dabartinio nežinomo reikšmes perdavimas MPI_Bcast(&IterResult, 1, MPI_DOUBLE, IterProcRank, MPI_COMM_WORLD); // Vektoriaus b reikšmių papildymas for (int j=0; j<RowNum; j++) if ( pProcPivotIter[j] < i ) { val = pProcRows[j*Size + i] * IterResult; pProcVector[j]=pProcVector[j] - val; } } } // Funkcija, skirta informacijai išvesti (Prad. ir tarp. duom.) void TestDistribution(double* pMatrix, double* pVector, double* pProcRows,
double* pProcVector, int Size, int RowNum) {
59
if (ProcRank == 0) { printf("Sugeneruota matrica A: \n"); PrintMatrix(pMatrix, Size, Size); printf("Sugeneruotas vektorius b: \n"); PrintVector(pVector, Size); } MPI_Barrier(MPI_COMM_WORLD); for (int i=0; i<ProcNum; i++) { if (ProcRank == i) { printf("\n Procesorius rangas = %d \n", ProcRank); printf("Matricos eilutė:\n"); PrintMatrix(pProcRows, RowNum, Size); printf(" Vektorius: \n"); PrintVector(pProcVector, RowNum); } MPI_Barrier(MPI_COMM_WORLD); } } // Funkcija skirta lygiagrečiam Gauso algoritmui vykdyti void ParallelResultCalculation(double* pProcRows, double* pProcVector,
double* pProcResult, int Size, int RowNum) { ParallelGaussianElimination (pProcRows, pProcVector, Size, RowNum); ParallelBackSubstitution (pProcRows, pProcVector, pProcResult, Size, RowNum); } // Funkcija skirta skaičiavimo proceso nutraukymui void ProcessTermination (double* pMatrix, double* pVector, double* pResult,
double* pProcRows, double* pProcVector, double* pProcResult) { if (ProcRank == 0) { delete [] pMatrix; delete [] pVector; delete [] pResult; } delete [] pProcRows; delete [] pProcVector; delete [] pProcResult; delete [] pParallelPivotPos; delete [] pProcPivotIter; delete [] pProcInd; delete [] pProcNum; } // Funkcija skirta rezultatų testavimui void TestResult(double* pMatrix, double* pVector, double* pResult, int Size) {
60
/* Atminties vieta skirta vektoriaus, kuris yra TLS skaičiavimų rezultatas ir kulkas yra nežinomas, saugojimui*/
double* pRightPartVector; // Žyme, rodanti ar vektorių dalis yra identiškos ar ne int equal = 0; double Accuracy = 1.e-6; // tikslumas if (ProcRank == 0) { pRightPartVector = new double [Size]; for (int i=0; i<Size; i++) { pRightPartVector[i] = 0; for (int j=0; j<Size; j++) { pRightPartVector[i] += pMatrix[i*Size+j]*pResult[pParallelPivotPos[j]]; } } for (int i=0; i<Size; i++) { if (fabs(pRightPartVector[i]-pVector[i]) > Accuracy) equal = 1; } if (equal == 1) printf("Realizacijų rezultatai skirtingi."); else printf("Abejų realizacijų rezultatai vienodi."); delete [] pRightPartVector; } } void main(int argc, char* argv[]) { double* pMatrix; // TLS matrica double* pVector; // Dešine TLS dalis double* pResult; // Vektorius-rezultatas double *pProcRows; // Eilučių skaičius matricos A, vienam procesui double *pProcVector; // Vektoriaus b blokai double *pProcResult; // Vektoriaus x blokai int Size; // Matricos ir vektoriaus dydis int RowNum; // Eilučių skaičius double start, finish, duration; setvbuf(stdout, 0, _IONBF, 0); MPI_Init ( &argc, &argv ); MPI_Comm_rank ( MPI_COMM_WORLD, &ProcRank ); MPI_Comm_size ( MPI_COMM_WORLD, &ProcNum ); if (ProcRank == 0) printf("Lygiagretus TLS Gauso metodo sprendimo programa\n"); //Atminties išskyrimas ir pradinių duomenų priskyrimas ProcessInitialization(pMatrix, pVector, pResult, pProcRows, pProcVector, pProcResult, Size,
RowNum); //Lygiagretaus Gauso algoritmo vykdymas
61
start = MPI_Wtime(); DataDistribution(pMatrix, pProcRows, pVector, pProcVector, Size, RowNum); ParallelResultCalculation(pProcRows, pProcVector, pProcResult, Size, RowNum); TestDistribution(pMatrix, pVector, pProcRows, pProcVector, Size, RowNum); ResultCollection(pProcResult, pResult); finish = MPI_Wtime(); duration = finish-start; if (ProcRank == 0) { // Nežinomųjų vektoriaus spausdinimas printf ("\n Vektorius x lygus: \n"); PrintResultVector(pResult, Size); } TestResult(pMatrix, pVector, pResult, Size); // Sugaišto laiko išvedimas į ekraną if (ProcRank == 0) printf("\n Sugaištas laikas: %f\n", duration); // Skaičiavimo proceso nutraukymas ProcessTermination(pMatrix, pVector, pResult, pProcRows, pProcVector, pProcResult); system("PAUSE"); MPI_Finalize(); }
3 priedas. Gauso metodo ciklinio duomenų pasiskirstymo lygiagretusis
algoritmas
#include "stdafx.h" #include<stdio.h> #include<mpi.h> #include<time.h> #include<memory.h> #include <stdlib.h> #include <math.h> #include <malloc.h> #define a(x,y) a[x*M+y] #define b(x) b[x] #define A(x,y) A[x*M+y] #define B(x) B[x] //Klaidos išmetimo funkcija void fatal(char *message) { printf("%s\n",message); exit(1); } //Atminties išvalymo funkcija void Environment_Finalize(double *a,double *b,double *x,double *f)
62
{ free(a); free(b); free(x); free(f); } //PAGRINDINĖ PROGRAMA int main(int argc, char **argv) { setvbuf(stdout, 0, _IONBF, 0); int M; //matricos dydis int m; //stulpelių paskirstymo kiekis kiekvienam procesui double *A; //TLS matrica double *B; //laisvųjų narių vektorius double starttime; //laiko kintamieji double time1; double time2; int p; //procesų kiekis int l; int i,j,t,k,my_rank; int i1,i2; int v,w; //paskirstyto stuleplio numeris double temp; int tem; double *sum; double *f; double lmax; double *a; double *b; double *x; int *shift; //Inicializavimas MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&p); MPI_Comm_rank(MPI_COMM_WORLD,&my_rank); //Pradinių duomenų generavimas if (my_rank==0) { starttime=MPI_Wtime(); /* realizacijos laiko pradzia */ printf("\n Įveskit matricos ir vektoriaus dydį: "); scanf("%d", &M); A=new double [M*M]; B=new double [M]; for (i=0; i<M; i++) { B[i] = rand()/double(1000); for (j=0; j<M; j++) { if (j <= i) A[i*M+j] = rand()/double(1000); else A[i*M+j] = 0; }
63
} } //Matricos procesams persiuntimas MPI_Bcast(&M,1,MPI_INT,0,MPI_COMM_WORLD); m=M/p; //stulpelių paskirstymo kiekis kiekvienam procesui if (M%p!=0) m++; //atminties išskyrimas pagalbiniams vektoriams f=new double [M+1]; a=new double [m*M]; b=new double [m]; sum=new double [m]; x=new double [M]; shift=new int [M]; if (a==NULL||b==NULL||f==NULL||sum==NULL||x==NULL||shift==NULL) fatal("allocate error\n"); //Masyvo užpildymas for(i=0;i<M;i++) shift[i]=i; //Aktyvių eilučių nuliniam procesui nustatymas if (my_rank==0) { for(i=0;i<m;i++) for(j=0;j<M;j++) a[i*M+j]=A[(i*p)*M+j]; for(i=0;i<m;i++) b(i)=B(i*p); } //Aktyvių eilučių persiuntimas kitiems procesams if (my_rank==0) { for(i=0;i<M;i++) if ((i%p)!=0) { i1=i%p; i2=i/p+1; MPI_Send(&A(i,0),M,MPI_DOUBLE,i1,i2,MPI_COMM_WORLD); MPI_Send(&B(i),1,MPI_DOUBLE,i1,i2,MPI_COMM_WORLD); } } /* my_rank==0 */ else /* my_rank !=0 */ { for(i=0;i<m;i++) { MPI_Recv(&a(i,0),M,MPI_DOUBLE,0,i+1,MPI_COMM_WORLD,&status); MPI_Recv(&b(i),1,MPI_DOUBLE,0,i+1,MPI_COMM_WORLD,&status); } } time1=MPI_Wtime(); /* skaičiavimo laiko pradžia */ //Matricos eliminavimo pradžia
64
for(i=0;i<m;i++) for(j=0;j<p;j++) { if (my_rank==j) { v=i*p+j; /* aktyvios eilutės numeris */ lmax=a(i,v); l=v; for(k=v+1;k<M;k++) if (fabs(a(i,k))>lmax) { lmax=a(i,k); l=k; } if (l!=v) { for(t=0;t<m;t++) { temp=a(t,v); a(t,v)=a(t,l); a(t,l)=temp; } tem=shift[v]; shift[v]=shift[l]; shift[l]=tem; } for(k=v+1;k<M;k++) a(i,k)=a(i,k)/a(i,v); b(i)=b(i)/a(i,v); a(i,v)=1; for(k=v+1;k<M;k++) f[k]=a(i,k); f[M]=b(i); //apskaičiuotų reikšmių nusiūntimas kitiems procesams MPI_Bcast(&f[0],M+1,MPI_DOUBLE,my_rank,MPI_COMM_WORLD); MPI_Bcast(&l,1,MPI_INT,my_rank,MPI_COMM_WORLD); } else { v=i*p+j; MPI_Bcast(&f[0],M+1,MPI_DOUBLE,j,MPI_COMM_WORLD); MPI_Bcast(&l,1,MPI_INT,j,MPI_COMM_WORLD); if (l!=v) { for(t=0;t<m;t++) { temp=a(t,v); a(t,v)=a(t,l); a(t,l)=temp;
65
} tem=shift[v]; shift[v]=shift[l]; shift[l]=tem; } } if (my_rank<=j) for(k=i+1;k<m;k++) { for(w=v+1;w<M;w++) a(k,w)=a(k,w)-f[w]*a(k,v); b(k)=b(k)-f[M]*a(k,v); } if (my_rank>j) for(k=i;k<m;k++) { for(w=v+1;w<M;w++) a(k,w)=a(k,w)-f[w]*a(k,v); b(k)=b(k)-f[M]*a(k,v); } } //rezultatų apskaičiavimas for(i=0;i<m;i++) sum[i]=0.0; for(i=m-1;i>=0;i--) for(j=p-1;j>=0;j--) if (my_rank==j) { x[i*p+j]=(b(i)-sum[i])/a(i,i*p+j); MPI_Bcast(&x[i*p+j],1,MPI_DOUBLE,my_rank,MPI_COMM_WORLD); for(k=0;k<i;k++) sum[k]=sum[k]+a(k,i*p+j)*x[i*p+j]; } else { MPI_Bcast(&x[i*p+j],1,MPI_DOUBLE,j,MPI_COMM_WORLD); if (my_rank>j) for(k=0;k<i;k++) sum[k]=sum[k]+a(k,i*p+j)*x[i*p+j]; if (my_rank<j) for(k=0;k<=i;k++) sum[k]=sum[k]+a(k,i*p+j)*x[i*p+j]; } //rezultatų persiuntimas if (my_rank!=0) for(i=0;i<m;i++) MPI_Send(&x[i*p+my_rank],1,MPI_DOUBLE,0,i,MPI_COMM_WORLD);
66
else for(i=1;i<p;i++) for(j=0;j<m;j++) MPI_Recv(&x[j*p+i],1,MPI_DOUBLE,i,j,MPI_COMM_WORLD,&status); //pabaigos laikas time2=MPI_Wtime(); //laiko spausdinimas if (my_rank==0) { printf("\n"); printf("Whole running time = %f seconds\n",time2-starttime); printf("Distribute data time = %f seconds\n",time1-starttime); printf("Parallel compute time = %f seconds\n",time2-time1); } MPI_Finalize(); Environment_Finalize(a,b,x,f); return(0); }
elementai, urie bus
lygūs 0