Lygiagretus programavimas sudėtingasPadaromastik labiau patyrusių programuotojųLygiagretūs šablonai nėra paplitę, gerai žinomi ir lengvai įgyvendinamiKrūva galimų problemų:Gijų varžymaisi (races)Mirties taškas (deadlock)Gyvas taškas (livelock)Pamiršti pranešimai (lost event notifications)…
Parallel Patterns Library(PPL)Veikia kaip ConcurrencyRuntimekomponentasAbstrakcijos lygis tarp programos ir gijų mechanizmoLengvas panaudojimasGalimybė plėstis (scalability)
6.
Struktūrinis ir nestruktūrinislygiagretumasStruktūrinis:Lygiagretus kodas pradedamas ir baigiamas viename konteksteUžduotis negali baigtis, kol nesibaigia jos dukterinės užduotysDidesnis našumasNestruktūrinis:Leidžia užduotį pradėti ir baigti ar jai laukti skirtinguose kontekstuoseLankstesnis
7.
PPL sudėtisLygiagrečios užduotys(Task Parallelism) Kelios užduotys lygiagrečiaiLygiagretūs algoritmai (Parallel Algorithms) Bendriniai algoritmai darbui su duomenų rinkiniaisLygiagrečios talpyklos ir objektai (Parallel containers & objects) Bendrinės talpyklos/objektai saugiam darbui su jų viduje esančiais elementais
8.
PPL: UžduotysUžduotis (Task)–skaičiavimas,kuris viduje gali būti išskaidytastask_handle klasėUžduočių grupė (Task group) – užduočių, formuojančių loginius skaičiavimus, grupėtask_group klasėstructured_task_group klasė
Užduotys. Kada/kur naudoti?RekursiniuosemetoduoseNorint išskaidyti darbą į atskiras dalisNorėdami aprašysi savo lygiagretų algoritmą, kai neužtenka standartinių PPL algoritmų.Jei galime, naudojame pastaruosius
PPL: AlgoritmaiPPL Algoritmaipanašūs į STL algoritmusIšnaudoja jau esamą ConcurrencyRuntimefunkctionalumąAlgoritmai:parallel_forparallel_for(begin,end,step,[](inti){ …});parallel_for_eachparallel_for(v.begin(),v.end(),[](inti){ … });parallel_invokeparallel_invoke([]{…},[]{…},[]{…},…,[]{…});
13.
parallel_for()Kartoja tą pačiąužduotį lygiagrečiaiOptimaliai išskaido užduotis lygiagrečiam vykdymuiBalansuoja tarp išskaidytų dalių priklausomai nuo apkrovų.Užduočių vykdymas neturi numatytos tvarkosArgumentai:Pradinė reikšmė, galinė reikšmė, žingsnis, funkcijaPradinė reikšmė, galinė reikšmė, funkcija (Žingsnis tokiu atveju pagal nutylėjimą = 1)
14.
for() parallel_for()Daugelįfor ciklų galima pakeisti parallel_for, tačiau:Ciklo indeksas (_Index_type) gali būti tik sveiko tipoIteracija gali vykti tik į priekį (jei žingsnis (_Step) mažesnis nei 1, gauna klaida)Pabaigos sąlyga turi būti konkreti. Iteracija baigiama, kai iteracijos kintamasis pasiekia reikšmę _Last
15.
parallel_for_each()Lygiagrečiai atlieka veiksmusiteruojamoje talpykloje (tarkim tokioje, kokias suteikia STL)Naudoja tą pačią užduočių skaidymo logiką kaip ir parallel_forUžduočių vykdymas taip pat neturi numatytos tvarkosVeikia tiek su einančiais į priekį (forward) iteratoriais, tiek su atsitiktinio priėjimo (randomaccess) iteratoriais. Su pastaraisiais greičiau.
16.
parallel_invoke()Vykdo užduočių rinkinįparaleliai.Nebaigia darbo tol, kol darbo nebaigia visos lygiagrečiai vykdomos užduotysPriima nuo 2 iki 10 parametrų – funkcijų, kurias vykdys. Kiekviena perduodama funkcija neturi turėti parametrų.Užduočių vykdymas taip pat neturi numatytos tvarkosPatogus, kai norima vykdyti keletą nepriklausomų užduočių lygiagrečiai
concurent_vectorNaudojimas panašus įSTL bibliotekos vector klasėsPapildymas, paėmimas, iteracija veikia lygiagrečiaiElementus pridėti galima tik į galą (nėra insert() metodo)Galima pašalinti visus elementus su clear() metodu. Šalinti vieno elemento negalima.Nesaugo savo elementų atmintyje iš eilės, tad negalima atlikti kai kurių masyvam būdingų operacijųGalima keisti dydį su grow_by() ir grow_to_at_least() (atitikmuo resize())
21.
concurent_queueNaudojimas panašus įSTL bibliotekos queue() klasėsLeidžia pasiekti pirmą (dequeue) ir paskutinį (enqueue) elementus.Nėra front() ir pop() metodų. Vietoj jų – try_pop()Nėraback() metodo, tad negalima kreiptis į eilės galąMetodu empty() galima patikrinti ar eilė tuščia.Iteracija ir bei dydžio gavimas nėra pritaikyti lygiagrečiam veikimu
22.
combinableSuteikia daug kartųnaudojamą saugyklą gijoje, iš kurių rezultatai sujungiami į bendrąNaudingas, kai reikia kažkokiu resursu dalintis keliose gijose/užduotyseNebereikia naudoti papildomų priemonių (tarkim mutex)combinable<int>sum;parallel_for_each(a.begin(),a.end(),[&](inti){sum.local()+=(is_prime(i)?i:0);});prime_sum=sum.combine(plus<int>());
Lygiagrečių užduočių stabdymasDubūdai sustabdyti:task_group::cancel() ir structured_task_group::cancel()Atšaukia užduočių grupę ir visas dukterines užduočių grupes (iš viršaus į apačią)EfektyvesnisIšimties (exception) išmetimas užduoties darbo funkcijoje.Atšaukinėja kiekvieną užduočių grupę atskirai (iš apačios į viršų)
25.
Lygiagrečių algoritmų stabdymasKadangiPPL lygiagretūs algoritmai veikia lygiagrečių užduočių pagrindu, jiems sustabdyti (atšaukti) galime naudoti tuos pačios būdus.structured_task_grouptg;task_group_statusstatus=tg.run_and_wait([&]{parallel_for(0,100,[&](inti){// Atšaukiam užduotį, kai pasiekiam 50if(i==50) {tg.cancel();}else{// Normalus darbas}});});
26.
(NE)stabdomLygiagretaus darbo stabdymas(atšaukimas) tinkamas naudoti, kai kiekviena susijusios grupės užduotis darbą gali baigti savo laikuYra atvejų, kai lygiagrečios užduočių grupės sustabdymas nėra geras sprendimas:Užduotis, kuri atblokuoja kitą aktyvią užduotį, nėra startavusi Ši užduotis nestartuoja, jei grupė atšaukiama Galimas mirties taškas (deadlock)