Mida tähendavad protsessori lõimed? Lühidalt asja juurde ja veidi tausta

Protsess(või ülesanne) on abstraktsioon, mis kirjeldab töötavat programmi.

OS jaoks protsessi tähistab tööühikut, süsteemiressursside tarbimise taotlust. Protsessihalduse alamsüsteem ajastab protsesside täitmise, s.o. jaotab protsessoriaja mitme samaaegselt süsteemis olemasoleva protsessi vahel ning tegeleb ka protsesside loomise ja hävitamisega, varustab protsesse vajalike süsteemiressurssidega ning toetab protsesside vahelist interaktsiooni.

Osa ressursse eraldatakse protsessile selle loomisel ja osa eraldatakse dünaamiliselt käitusajal päringute alusel. Protsessile saab ressursse määrata kogu selle elueaks või ainult teatud perioodiks. Nende funktsioonide täitmisel suhtleb protsessihalduse alamsüsteem teiste ressursside haldamise eest vastutavate OS-i alamsüsteemidega, nagu mäluhalduse alamsüsteem, sisendi/väljundi alamsüsteem ja failisüsteem. Kui süsteemis tehakse korraga mitu iseseisvat ülesannet, tekivad probleemid. lisaprobleeme. Kuigi protsessid tekivad ja käivituvad asünkroonselt, võivad nad vajada suhtlemist, näiteks andmete vahetamisel. Protsessi kiiruste sobitamine on samuti väga oluline, et vältida võistlustingimusi, kus mitu protsessi üritavad muuta sama faili, ummikseisu või muid kokkupõrkeid, mis tekivad ressursside jagamisel. Protsesside sünkroniseerimine on protsessihalduse alamsüsteemi üks olulisi funktsioone.

Iga kord, kui protsess lõpeb, sulgeb protsessihalduse alamsüsteem kõik failid, millega protsess töötas, vabastades RAM-i, mis on eraldatud protsessi koodide, andmete ja süsteemiteabe struktuuride jaoks. Kõik võimalikud OS-i järjekorrad ja ressursside loendid, mis sisaldavad viiteid lõpetatavale protsessile, parandatakse.

Multiprogrammeerimise toetamiseks peab OS ise määratlema ja kujundama need sisemised tööüksused, mille vahel protsessor ja muud arvutiressursid jaotatakse. Seda tuleb meenutada multiprogrammeerimine on organiseerimisviis arvutusprotsess, milles arvutimälus on mitu programmi, mida vaheldumisi ühes protsessoris täidetakse.

Praegu määratleb enamik operatsioonisüsteeme kahte tüüpi tööühikuid. Suurem tööüksus, mida tavaliselt nimetatakse protsessiks või ülesandeks, nõuab mitme väiksema töö lõpetamist, mida nimetatakse lõimeks või lõimeks.

Ilmselgelt koosneb igasugune arvutisüsteemi toiming mõne programmi täitmisest. Seetõttu on nii protsessi kui ka lõimega seotud teatud programmikood, mis on selleks otstarbeks kujundatud käivitatava mooduli kujul. Selle programmikoodi täitmiseks tuleb see laadida RAM-i, võib-olla eraldatud kettaruumi andmete salvestamiseks, juurdepääsuks sisend/väljundseadmetele, nt. jadaport. Käitamise ajal võib programm vajada juurdepääsu ka HI-le, näiteks failidele. Ja loomulikult on võimatu programmi käivitada ilma seda pakkumata CPU aeg, st. aeg, mille jooksul protsessor täidab antud programmi koode.

Süsteemides, kus on olemas nii protsessid kui ka lõimed, käsitleb OS seda protsessi kui soovi tarbida igat tüüpi ressursse, välja arvatud ühe protsessori aeg. Seda viimast kõige olulisemat ressurssi jagab OS teiste tööüksuste - lõimede vahel, mis said oma nime tänu sellele, et nad esindavad käskude jadasid (käskude täitmislõime).

Lihtsamal juhul koosneb protsess ühest lõimest ja nii tõlgendati mõistet “protsess” kuni 1980. aastate keskpaigani ning samal kujul on see säilinud ka mõnes kaasaegses operatsioonisüsteemis. Seda tüüpi süsteemides on mõiste "vool" täielikult absorbeeritud mõistega "protsess", st. Jääb vaid üks töö ja ressursitarbimise ühik - protsess. Multiprogrammeerimine toimub sellistes operatsioonisüsteemides protsessi tasemel.

Protsessil on kolm põhiolekut: valmis, töötab ja blokeeritud.

Ühe protsessoriga süsteemis saab töötada ainult üks protsess. Samal ajal võib olla mitu valmis ja blokeeritud protsessi, mis ootavad mõne sündmuse (näiteks I/O) toimumist. Sel juhul on valmis protsesside loend järjestatud prioriteedi järgi.

Et protsessid ei segaks ressursside jaotamist ning ei kahjustaks üksteise koode ja andmeid, peab OS otsustama kõige tähtsam ülesanne– isoleerida üks protsess teisest.

Selle saavutamiseks varustab OS igale protsessile eraldi virtuaalse aadressiruumi, et ükski protsess ei pääseks otse juurde teise protsessi käskudele ja andmetele.

Töötle virtuaalset aadressiruumi on aadresside kogum, mida saab töödelda protsessiprogrammi mooduliga.

Operatsioonisüsteem kaardistab protsessi virtuaalse aadressiruumi protsessile eraldatud füüsilise mäluga.

Kui interaktsioon on vajalik, pöörduvad protsessid OS-i poole, mis vahendajana pakub neile protsessidevahelise suhtluse vahendeid - torujuhtmeid, postkastid, jagatud mälu jaotised ja mõned teised.

Kuid süsteemides, millel pole lõime mõistet, tekivad protsessis paralleelsete arvutuste korraldamisel probleemid. Ja selline vajadus võib tekkida. Tõepoolest, multiprogrammeerimisega see suureneb läbilaskevõime süsteem, kuid eraldi protsessi ei saa kunagi kiiremini teostada kui ühe programmi režiimis (igasugune ressursside jagamine ainult aeglustab ühe osaleja tööd, kuna kulub ressursi kättesaadavaks saamist ootama täiendavalt). Ühe protsessi sees töötaval rakendusel võib aga olla sisemine paralleelsus, mis võiks põhimõtteliselt võimaldada selle lahendamist kiirendada. Kui programm näeb ette näiteks juurdepääsu välisseadmele, siis selle toimingu ajal on võimalik mitte blokeerida kogu protsessi täitmist, vaid jätkata arvutusi mõnes teises programmi harus. Mitme töö paralleelne käitamine ühes interaktiivses rakenduses parandab kasutaja efektiivsust. Seega on tekstiredaktoriga töötades soovitav osata uue teksti tippimist kombineerida aeganõudvate toimingutega nagu olulise osa teksti ümbervormindamine, dokumendi printimine või salvestamine kohalikule või kaugkettale.

Lõngad tekkisid OS-is arvutuste paralleelsuse vahendina. Muidugi saab ühe rakenduse piires arvutuste paralleelsuse probleemi lahendada traditsiooniliste meetoditega.

Esiteks, rakenduste programmeerija võib võtta endale paralleelsuse korraldamise keeruka ülesande, valides rakenduses kindla dispetšeri alamprogrammi, mis annab perioodiliselt juhtimise üle ühele või teisele arvutusharule. Sel juhul osutub programm loogiliselt väga segaseks, arvukate juhtimise üleandmistega, mis raskendab oluliselt selle silumist ja muutmist.

Teiseks on lahenduseks luua ühe rakenduse jaoks iga paralleeltöö jaoks mitu protsessi. Standardsete OS-i tööriistade kasutamine protsesside loomiseks ei võimalda aga arvestada asjaoluga, et need protsessid lahendavad ühe probleemi, mis tähendab, et neil on palju ühist – nad saavad töötada samade andmetega, kasutada sama koodi. segmenti ning neile antakse samad ja samad juurdepääsuõigused arvutisüsteemi ressurssidele.

OS-is on koos protsessidega vaja teist arvutuste paralleelseks muutmise mehhanismi, mis võtaks arvesse tihedaid seoseid sama rakenduse arvutuste üksikute harude vahel.

Nendel eesmärkidel pakuvad kaasaegsed operatsioonisüsteemid mitme lõimega mehhanismi. Samal ajal võetakse kasutusele uus tööüksus - täitmise niit ja mõiste “protsess” muudab oma tähendust suurel määral. Mõiste "lõime" vastab protsessori järjestikusele üleminekule ühelt programmijuhiselt teisele. Operatsioonisüsteem jaotab protsessori aja lõimede vahel. OS määrab protsessile aadressiruumi ja ressursside komplekti, mida jagatakse kõigi selle lõimede vahel.

Üheprogrammilistes süsteemides ei ole vaja kasutusele võtta tööühikut tähistavat mõistet, kuna puudub ressursside jagamise probleem.

Lõimide loomine nõuab OS-ilt vähem üldkulusid kui protsessid. Erinevalt protsessidest, mis kuuluvad erinevatesse konkureerivatesse rakendustesse, kuuluvad ühe protsessi kõik lõimed alati samasse rakendusse, mistõttu OS isoleerib lõime palju vähemal määral kui traditsioonilise mitmeprogrammilise süsteemi protsessid. Kõik ühe protsessi lõimed kasutavad ühiseid faile, taimereid, seadmeid, sama RAM-i ala ja sama aadressiruumi. See tähendab, et neil on samad globaalsed muutujad. Kuna igal lõimel on juurdepääs protsessi mis tahes virtuaalsele aadressile, saab üks lõim kasutada teise lõime pinu. Sama protsessi lõimede vahel pole täielikku kaitset, sest esiteks on see võimatu ja teiseks pole see vajalik. Interaktsiooni ja andmevahetuse korraldamiseks ei pea lõimed üldse OS-ile juurde pääsema; nad peavad lihtsalt kasutama ühismälu - üks lõim kirjutab andmeid ja teine ​​loeb neid. Teisest küljest voolab erinevad protsessid on endiselt üksteise eest hästi kaitstud.

Multiprogrammeerimine on tõhusam pigem lõime kui protsessi tasemel. Igal lõimel on oma programmiloendur ja pinu. Ühe protsessi sees mitme lõimena kavandatud ülesande saab kiiremini täita selle üksikute osade pseudoparalleelsel (või mitmeprotsessorilises süsteemis paralleelselt) täitmisel. Multithreadingut saab eriti tõhusalt kasutada hajutatud rakenduste käitamiseks; näiteks võib mitme lõimega server täita paralleelselt mitme kliendi päringuid.

Lõimede kasutamine ei ole seotud mitte ainult sooviga suurendada süsteemi jõudlust paralleelse andmetöötluse kaudu, vaid ka eesmärgiga luua loetavamaid, loogilisemaid programme. Mitme täitmislõime kasutuselevõtt lihtsustab programmeerimist. Näiteks kirjutaja-lugeja ülesannetes kirjutab üks lõim puhvrisse ja teine ​​loeb sellest. Kuna neil on ühine puhver, ei tohiks te neid teha eraldi protsessid. Teine näide lõimede kasutamisest on selliste signaalide juhtimine nagu klaviatuuri katkestused (Del või Break). Katkestussignaali käsitlemise asemel määratakse üks lõim pidevalt signaalide saabumist ootama. Seega võib lõimede kasutamine vähendada vajadust kasutajataseme katkestuste järele. Nendes näidetes ei ole paralleelne täitmine nii oluline kui programmi selgus.

Suurim efekt mitmelõimelise töötlemise kasutuselevõtust saavutatakse mitme protsessoriga süsteemides, kus lõime, sealhulgas samasse protsessi kuuluvaid, saab erinevatel protsessoritel täita tõeliselt paralleelselt (mitte pseudoparalleelselt).

Loo protsess Esiteks tähendab see protsessi deskriptori loomist, mis on üks või mitu teabestruktuuri, mis sisaldab kogu teavet protsessi kohta, mida OS vajab selle haldamiseks. Selline teave võib sisaldada näiteks protsessi identifikaatorit, teavet käivitatava mooduli mälu asukoha kohta, protsessi privileegi määra (prioriteet ja juurdepääsuõigused) jne.

Protsessi deskriptorite näideteks on OS/360 ülesande juhtimisplokk (TCB), OS/2 protsessijuhtimise plokk (PCB), UNIX-i protsessikäepide, Windows NT objektprotsess.

Protsessi deskriptori loomine tähistab järjekordse konkurendi tekkimist arvutusressursside osas süsteemis. Sellest hetkest alates peab OS ressursside jaotamisel arvestama uue protsessi vajadustega.

Protsessi loomine hõlmab käivitatava programmi koodide ja andmete laadimist seda protsessi kettalt RAM-i. Selleks peab OS tuvastama sellise programmi asukoha kettal, jaotama ümber RAM-i ja eraldama mälu uue protsessi käivitatavale programmile. Seejärel tuleb programm lugeda talle eraldatud mälupiirkondadesse ja võimalusel muuta programmi parameetreid olenevalt asukohast mälus.

Virtuaalmäluga süsteemides saab alghetkel laadida vaid osa protsessikoodist ja andmetest, et ülejäänud vastavalt vajadusele “üles pumbata”. On süsteeme, milles protsessi loomise etapis ei pea tingimata koode ja andmeid RAM-i laadima, selle asemel kopeeritakse käivitatav moodul sellest kataloogist failisüsteem, kus see algselt asus, vahetusalasse - eriline ala protsessikoodide ja andmete salvestamiseks eraldatud ketas. Kõigi nende toimingute tegemisel suhtleb protsessihalduse alamsüsteem tihedalt mäluhalduse alamsüsteemi ja failisüsteemiga.

Mitme lõimega süsteemis loob OS protsessi loomisel iga protsessi jaoks vähemalt ühe täitmislõime. Lõime loomisel, nagu ka protsessi loomisel, genereerib OS spetsiaalse infostruktuuri - lõime deskriptori, mis sisaldab lõime identifikaatorit, juurdepääsuõigusi ja prioriteetseid andmeid, lõime olekut ja muud teavet. Algolekus on niit (või protsess, kui me räägime süsteemist, milles mõiste "lõng" pole defineeritud) peatatud olekus. Täitmiseks lõime valimise hetk toimub vastavalt selles süsteemis aktsepteeritud protsessori aja andmise reeglile ja võttes arvesse kõiki olemasolevaid Sel hetkel niidid ja protsessid. Kui protsessikoodid ja andmed asuvad vahetusalas, on protsessilõime aktiveerimise vajalik tingimus ka RAM-i ruumi olemasolu selle käivitatava mooduli laadimiseks.

Paljudes süsteemides võib lõime paluda OS-il luua nn järeltulijad. Erinevad operatsioonisüsteemid struktureerivad alamlõimede ja nende vanemate vahelisi suhteid erinevalt. Näiteks mõnes operatsioonisüsteemis sünkroonitakse lähtelõime täitmine selle järglastega; eriti pärast emalõime valmimist võib OS peatada kõigi oma järglaste käitamise. Teistes süsteemides võivad alamlõimed käitada põhilõime suhtes asünkroonselt. Järeltulijad pärivad tavaliselt palju oma emavoogude omadusi. Paljudes süsteemides on laste kudemine protsesside ja lõimede loomise peamine mehhanism.

Protsessi planeerimine hõlmab järgmiste ülesannete lahendamist:

■ teostatava protsessi muutmise ajamomendi määramine;

■ käivitatava protsessi valimine valmis protsesside reast;

■ "vanade" ja "uute" protsesside kontekstide vahetamine.

Esimesed kaks probleemi on lahendatud tarkvara, ja viimane on suures osas riistvarapõhine.

On palju erinevaid protsesside planeerimise algoritme, mis lahendavad loetletud probleeme erineval viisil, taotlevad erinevaid eesmärke ja pakuvad erineva kvaliteediga multiprogrammeerimist. Selle algoritmide komplekti hulgas vaatleme lähemalt kahte kõige levinumate algoritmide rühma: kvantimispõhised algoritmid ja prioriteedipõhised algoritmid.

Kooskõlas kvantiseerimisel põhinevad algoritmid, Aktiivse protsessi muutus toimub, kui:

■ protsess lõppes ja süsteemist lahkus;

■ ilmnes viga;

■ protsess on jõudnud ooteolekusse;

■ sellele protsessile eraldatud protsessori ajalõik on ammendatud.

Protsess, mis on oma kvanti ammendanud, asetatakse "valmis" olekusse ja ootab, kuni talle antakse uus protsessori ajakvant, ning valitakse täitmiseks teatud reegli järgi. uus protsess valmisjärjekorrast. Nii ei hõivata ükski protsess CPU-d kaua, mistõttu kasutatakse ajajagamissüsteemides laialdaselt kvantiseerimist.

Protsessidele eraldatud kvantid võivad olla kõikide protsesside jaoks samad või erinevad. Ühele protsessile eraldatud kvantid võivad olla kindla väärtusega või protsessi eluea erinevatel perioodidel varieeruda. Protsessid, mis pole neile eraldatud kvanti täielikult ära kasutanud (näiteks I/O aktiivsuse tõttu), võivad hilisema hoolduse käigus saada hüvitist privileegidena, kuid ei pruugi saada. Valmis protsesside järjekorda saab korraldada erinevalt: tsükliliselt, vastavalt reeglile “first in, first out” (FIFO) või reegli “viimane sisse, esimene välja” (LIFO) järgi.

IN prioriteedipõhised algoritmid kasutatakse protsessi "prioriteedi" mõistet.

Prioriteet– see on arv, mis iseloomustab protsessi privileegi astet ressursside kasutamisel arvuti, eriti CPU aeg: mida kõrgem on prioriteet, seda suuremad õigused.

Prioriteeti saab väljendada täis- või murdarvuna, positiivsete või negatiivsete väärtustena. Mida suuremad on protsessi privileegid, seda vähem aega see järjekordades veedab. Prioriteedi saab määrata otse süsteemiadministraator sõltuvalt töö olulisusest või makstavast tasust või arvutada OS ise teatud reeglite järgi, see võib jääda fikseerituks kogu protsessi eluea jooksul või aja jooksul muutuda vastavalt mingi seadus. Viimasel juhul nimetatakse prioriteedid dünaamiline.

On kahte tüüpi prioriteetseid algoritme: suhtelisi prioriteete kasutavad algoritmid ja absoluutseid prioriteete kasutavad algoritmid.

Mõlemal juhul toimub protsessi valimine valmisjärjekorrast täitmiseks samal viisil: valitakse kõrgeima prioriteediga protsess. Aktiivse protsessi muutumise hetke määramise probleem lahendatakse erineval viisil. Süsteemides suhtelised prioriteedid Aktiivne protsess töötab seni, kuni see protsessorist ise lahkub, minnes "blokeerimisolekusse" (või ilmneb tõrge või protsess lõpeb). Süsteemides koos absoluutsed prioriteedid aktiivse protsessi täitmine katkeb veel ühel tingimusel: kui valmis protsesside järjekorda ilmub protsess, mille prioriteet on kõrgem kui aktiivse protsessi prioriteet. Sel juhul läheb katkestatud protsess valmisolekusse.

Paljudes operatsioonisüsteemides koostatakse ajastamisalgoritmid nii kvantiseerimise kui ka prioriteetide abil. Näiteks ajastamine põhineb kvantiseerimisel, kuid kvantväärtuse ja (või) protsessi valmisolekute järjekorrast valimise järjekorra määravad protsesside prioriteedid.

Protsessi ajastamise protseduure on kahte peamist tüüpi: ennetav ja mitteennetav.

Mitte-ennetav multitegumtöö(Non-preemptive multitegumtöö) on protsesside ajastamise meetod, mille puhul aktiivne protsess jookseb seni, kuni see omal algatusel annab OS-i planeerijale juhtimise, nii et see valib järjekorrast teise töövalmis protsessi.

Ennetav multitegumtöö(Ennetav multitegumtöötlus) on meetod, mille puhul otsuse lülitada protsessor ühe protsessi täitmiselt teise täitmisele vastu OS-i planeerija, mitte aktiivne tegum ise.

Mõisteid “ennetav” ja “mittepreventiivne” samastatakse mõnikord prioriteetsete ja mitteprioriteetsete distsipliinide mõistetega, mis on täiesti vale, samuti absoluutse ja suhtelise prioriteedi mõistega, mis on osaliselt vale. Ennetav ja mitte-ennetav multitegumtöö on laiemad mõisted kui prioriteetsed tüübid. Ülesande prioriteete võib kasutada või mitte kasutada nii ennetavas kui ka mitteennetavas plaanimismeetodis. Seega võib prioriteetide kasutamise korral relatiivsete prioriteetide distsipliini liigitada mitteennetava multitegumtööga süsteemide klassi ja absoluutsete prioriteetide distsipliini ennetava multitegumtöötlusega süsteemide klassi. Mitteprioriteetse ajastamise distsipliin, mis põhineb võrdsete ajalõikude eraldamisel kõikidele ülesannetele, viitab ennetavatele algoritmidele.

Peamine erinevus ennetava ja mitteennetava multitegumtöö vahel on ülesannete ajastamise mehhanismi tsentraliseerituse aste. Kell ennetav multitegumtööülesannete ajastamise mehhanism on täielikult koondunud OS-i ja programmeerija kirjutab oma rakenduse, muretsemata, et seda täidetakse paralleelselt teiste ülesannetega. Sel juhul toimib OS järgmisi funktsioone: määrab hetke, millal aktiivne ülesanne täitmisest eemaldatakse, jätab selle konteksti meelde, valib järjekorrast valmis ülesanded järgmise ja käivitab selle täitmiseks, laadides selle konteksti. Kell mitteennetav multitegumtöö Ajastusmehhanism jaotatakse süsteemi ja rakendusprogrammide vahel. OS-ilt juhtimise saanud rakendusprogramm määrab ise oma järgmise iteratsiooni lõpuleviimise hetke ja edastab juhtimise mõne süsteemikõne abil OS-ile ning OS moodustab ülesannete järjekorrad ja valib täitmiseks järgmise ülesande vastavalt mõnele. algoritm (näiteks prioriteete arvesse võttes) . See mehhanism tekitab probleeme nii kasutajatele kui ka arendajatele.

Kasutajate jaoks tähendab see, et juhtimine süsteemi üle kaob suvaliseks ajaks, mille määrab rakendus (mitte kasutaja). Kui rakendus kulutab mõne töö tegemiseks liiga palju aega, näiteks ketta vormindamiseks, ei saa kasutaja sellelt ülesandelt teisele toimingule lülituda, näiteks tekstiredaktor, samas kui vormindamine jätkuks taustal. See olukord on ebasoovitav, kuna kasutajad ei taha tavaliselt kaua oodata, kuni masin oma ülesande täitma hakkab. Seetõttu peavad ennetava töökeskkonna rakenduste arendajad, võttes endale planeerija funktsioonid, looma rakendused, mis täidavad oma ülesandeid väikestes osades. Näiteks vormindamisprogramm saab vormindada ühe disketi raja ja tagastada süsteemile juhtimise. Pärast muude ülesannete täitmist tagastab süsteem juhtimise vormindajale järgmise loo vormindamiseks. See ülesannete vahel aja jagamise meetod töötab, kuid raskendab oluliselt programmide väljatöötamist ja seab programmeerija kvalifikatsioonile kõrgendatud nõudmised. Programmeerija peab tagama, et tema programm oleks "sõbralik" teiste samaaegselt töötavate programmide suhtes, andes neile üsna sageli kontrolli. Rakenduse "ebasõbralikkuse" äärmuslik ilming on selle külmutamine, mis toob kaasa üldise süsteemi krahhi. Ennetava multitegumtööga süsteemides on sellised olukorrad tavaliselt välistatud, kuna keskne ajastamismehhanism eemaldab takerdunud ülesande täitmisest.

Planeerija funktsioonide jaotamine süsteemi ja rakenduste vahel ei ole aga alati puudus ning teatud tingimustel võib see olla eelis, kuna see võimaldab rakenduse arendajal kavandada antud fikseeritud ülesannete komplekti jaoks kõige sobivama ajastamisalgoritmi. Kuna arendaja määrab ise programmis ajahetke, millal kontroll tagastatakse, siis välistab see programmide irratsionaalsed katkestused “ebamugavatel” ajahetkedel. Lisaks on andmete jagamise probleemid kergesti lahendatavad: ülesanne kasutab seda iga iteratsiooni ajal eranditult ja on kindel, et keegi teine ​​ei muuda neid andmeid selle perioodi jooksul. Nihkesüsteemide oluline eelis on rohkem suur kiirusülesandelt ülesandele lülitumine.

Mitteennetava multitegumtöötluse tõhusa kasutamise näide on NetWare failiserver, mis suuresti tänu sellele on saavutanud suure failitoimingute kiiruse.

Peaaegu kõik kaasaegsed operatsioonisüsteemid, mis on keskendunud suure jõudlusega rakenduste täitmisele (UNIX, Windows NT, OS/2, VAX/VMS), rakendavad aga ennetavat multitegumtöötlust. Viimasel ajal on pööre tulnud lauaarvutiklassi OS-ide poole. Võib-olla sel põhjusel kutsutakse sageli ennetavaks multitegumtööks tõsi.

7 vastust

See sõltub riistvarast, kuna te (võib-olla) ei kasuta teoreetiline arvuti, kuid füüsiline riistvara, seega on teil piiratud ressursid.

Isegi kui teil võib olenevalt riistvarast töötada 5000+ lõime, võib see olla palju aeglasem kui 10 lõimega samaväärne programm. Ma arvan, et peaksite uurima lõimede ühendamist.

Tavaliselt määrab samaaegselt töötavate lõimede arvu teie protsessorite ja CPU tuumade arv (sh hüperlõime). See tähendab, et igal ajahetkel on töötavate lõimede arv (operatsioonisüsteemis) võrdne "tuumade" arvuga.

Kui palju lõime saate oma rakenduses samaaegselt käivitada, sõltub sellest suur kogus tegurid. Parim number(kerge inimene) oleks tuumade arv masinal, aga loomulikult nagu keegi ei teeskle (muu rakendust pole :).

Kui aus olla, siis ma ütlen, et teen .NET-is/Windowsis palju mitmelõimega töötlemist, sest inimene teeb tavaliselt rohkem kahju kui kasu, kui sul pole tegelikku arusaamist. NET-il on lõimekogumi kontseptsioon ja sa pead teada, kuidas see lisaks Windowsile töötab.

Versioonides .NET 3.5/4.0 peaksite vaatama Task Parallel Library, kuna teek suudab palju paremini määrata, mitu lõime (kui üldse) luua. TPL-iga saab threadpool põhjaliku uuenduskuuri ning on lõime korrutamise ja ülesannete varastamise jms osas palju targem. Kuid tavaliselt töötate ülesannetega, mitte lõimedega.

See on keeruline valdkond ja selle tulemusena tutvustas .NET-i platvorm Tasksit, et programmeerijad lõimedest eemale viia ja võimaldada käitusajal selles osas nutikalt käituda, samas kui programmeerija ütleb lihtsalt seda, mida ta tahab ja mitte niivõrd, kuidas seda teha. see.

Iga lõim tarbib rohkem mälu (kerneli pinu, lõime keskkonnaplokk, lõime kohalik, pinu...). AFAIK pole Windowsis selget piirangut, nii et piirang oleks mälu (ilmselt lõimepõhine pinu).

IN Linuxi lõimed rohkem sarnaseid protsesse (jagatud mälu) ja te piirdute:

Cat /proc/sys/kernel/threads-max

Üsna hea rusikareegel intensiivsete ülesannete täitmisel on sooritada sama arv, mis on teie füüsilise tuuma arvuga.

Jah, saate käivitada rohkem ülesandeid, kuid need ootavad ressursse (või lõime lõimede kogumis) ja teie kast, olenemata suurusest, ei saa kõiki peamisi protsessori ressursse täielikult eraldada 100% lõime tausta tõttu muud protsessid. Seega, mida rohkem ülesandeid loote, seda rohkem lõime loote, kuna nende arv ületab tegelikke võimalikke paralleellõime (1 tuuma kohta), seda rohkem tehakse ressursside haldamist, järjekorda seadmist ja vahetamist.

Test, mille me praegu läbisime, kui ma töötan, kasutades käivitamiseks viirusemalli lisaülesandeid, näitas, et optimaalne tase on ligilähedane protsessori skoorile. Üks-ühele suhtega koos füüsilise tuumade arvuga ülesanded kestsid umbes 1 minut ülesande kohta. Kui seadistatud protsessoriloendur kahekordistama, läks ülesande täitmise aeg keskmiselt 1 minutilt 5 minutile. See muutub geomeetriliselt aeglasemaks, mida rohkem ülesandeid kernel algatab.

Näiteks kui teil on 8 füüsilist tuuma, siis peaks kõige kiiremini olema 8 ülesannet (ja TPL-i kasutades sisuliselt 8 samaaegset lõime aktiivses protsessis). Seal on teie põhilõng või protsess, mis loob muid ülesandeid ja muid taustprotsesse, kuid kui kast on ressursikasutuse nautimiseks üsna isoleeritud, on need üsna minimaalsed.

Teie ülesannete piiriku programmeerimispind põhineb tuumade loendusel, kui närid ülesandeid järjekorrast või loendist, nii et kui juurutate rakenduse erineva suurusega kastidesse, kohandub see automaatselt.

Selle programmiliseks määratlemiseks kasutame

var CoreCount = System.Environment.ProcessorCount / 2;

Miks jagada kahega, küsite? Sest peaaegu kõike kaasaegsed protsessorid kasutage loogilisi südamikke või hüperlõime. Peaksite oma testimisega avastama, et kui kasutate loogilist loendust, väheneb teie üldine kiirus ülesande kohta ja seega kogu protsess oluliselt. Füüsilised tuumad on võti. Me ei näinud kiire tee leida füüsiline vs loogiline aga kiire ülevaade on näidanud, et see on alati tõsi. YMMV, kuid see võib üsna kiiresti minna.

Suutsin oma praeguses vanas protsessoris (2005) korraga käivitada 4 lõime. EVGA CPU-kirjuti kasutamine enne CPU-summi kõlamist. (Programmeeritud BIOS-i menüüs). i väärtus ületas 90 * c. Pidage meeles, et me räägime samaaegselt töötavatest andmevoogudest. hea näide oleks mitme programmi samaaegne avamine. Kuid üldiselt sõltub see sellest, kui hea on teie protsessor multitegumtöös. (teisisõnu, paljusid aktiivseid lõime saab töödelda). Ohutul viisil testimine on laadida "ocscanner (By EVGA)" ja "CPU Thermometer" kasutades CPU-d OC-skannerisse. Testimise ajal veenduge, et teie temperatuur ei tõuseks üle 90*c (või mis tahes temperatuuri, mille juures tunnete end turvaliselt) ja vaadake praegust niitide arvu, mida te oma protsessorile viskate. alustage 2 lõimega, oodake 3-5 minutit, jälgides protsessori temperatuuri, lisage veel üks lõime, korrake. (ÄRGE VÕTKE OMA ÕNNE!!!) (ÄRGE PROOVIGE, KUI CPU TERMOMEETER EI SAADA TEEMPERATUURI!!!)

  • Õpetus

Selles artiklis püüan kirjeldada terminoloogiat, mida kasutatakse süsteemide kirjeldamiseks, mis on võimelised käivitama paralleelselt mitut programmi, st mitmetuumaline, mitme protsessoriga, mitme keermega. Erinevad tüübid aastal ilmus paralleelsus IA-32 protsessoris erinev aeg ja mõnevõrra ebajärjekindlas järjekorras. Selles kõiges on üsna lihtne segadusse sattuda, eriti kui arvestada, et operatsioonisüsteemid peidavad detaile hoolikalt vähem keerukate rakendusprogrammide eest.

Artikli eesmärk on näidata, et mitmeprotsessoriliste, mitmetuumaliste ja mitme keermega süsteemide võimalike konfiguratsioonide kogu varieeruvuse juures luuakse nendel töötavatele programmidele võimalused nii abstraktsiooniks (erinevuste ignoreerimiseks) kui ka spetsiifikaga arvestamiseks ( võimalus konfiguratsiooni programmiliselt välja selgitada).

Hoiatus artiklis olevate ®, ™ märkide eest

Minu kommentaar selgitab, miks peaksid ettevõtte töötajad avalikus suhtluses kasutama autoriõiguste märkusi. Selles artiklis pidin neid üsna sageli kasutama.

Protsessor

Muidugi on vanim, sagedamini kasutatav ja vastuoluline termin "protsessor".

IN kaasaegne maailm protsessor on see, mida me ostame ilusas jaemüügikarbis või mitte nii kenas OEM-i pakendis. Jagamatu üksus, mis on sisestatud emaplaadi pesasse. Isegi kui pistikut pole ja seda ei saa eemaldada, st kui see on tihedalt joodetud, on see üks kiip.

Mobiilsüsteemidel (telefonid, tahvelarvutid, sülearvutid) ja enamikul lauaarvutitel on üks protsessor. Mõnikord on tööjaamadel ja serveritel ühel emaplaadil kaks või enam protsessorit.

Mitmekordne tugi keskprotsessoridühes süsteemis nõuab selle disainis mitmeid muudatusi. Vähemalt on vaja tagada nende füüsiline ühendus (pakkuma emaplaadil mitu pistikupesa), lahendada protsessori tuvastamise probleemid (vt hiljem käesolevas artiklis ja ka minu eelmist märkust), mälule juurdepääsu koordineerimine ja edastamise katkestamine ( katkestuskontroller peab suutma mitme protsessori katkestusi suunata) ja loomulikult ka operatsioonisüsteemi tugi. Kahjuks ei leidnud ma dokumentaalset mainimist esimese mitmeprotsessorilise süsteemi loomisest Inteli protsessoritel, kuid Wikipedia väidab, et Sequent Computer Systems tarnis neid juba 1987. aastal, kasutades Intel 80386 protsessoreid. Mitme kiibi tugi ühes süsteemis on muutumas laialdaseks , alustades Intel® Pentiumist.

Kui protsessoreid on mitu, on igal neist tahvlil oma pistik. Igal neist on täielikud sõltumatud koopiad kõigist ressurssidest, nagu registrid, täitmisseadmed, vahemälud. Neil on ühine mälu – RAM. Mälu saab nendega siduda mitmel ja üsna mittetriviaalsel viisil, kuid see teine ​​lugu, mis jääb selle artikli reguleerimisalast välja. Oluline on see, et igal juhul tuleks käivitatavate programmide jaoks luua illusioon homogeensest ühismälust, millele pääseb juurde kõigist süsteemi kuuluvatest protsessoritest.


Valmis startima! Intel® Desktop Board D5400XS

Tuum

Ajalooliselt ilmusid Intel IA-32 mitmetuumalised tuumad hiljem kui Intel® HyperThreading, kuid loogilises hierarhias on see järgmine.

Näib, et kui süsteemil on rohkem protsessoreid, on selle jõudlus suurem (ülesannete puhul, mis saavad kasutada kõiki ressursse). Kui aga nendevahelise suhtluse hind on liiga kõrge, siis kogu paralleelsusest saadava kasu tapavad pikad viivitused ühiste andmete edastamisel. Just seda täheldatakse ka mitme protsessoriga süsteemides – nii füüsiliselt kui loogiliselt on need üksteisest väga kaugel. Sest efektiivne suhtlus Sellistes tingimustes on vaja välja pakkuda spetsiaalsed siinid, näiteks Intel® QuickPath Interconnect. Energiakulu, lõpplahenduse suurus ja hind see kõik muidugi ei vähene. Peaks appi tulema kõrge integreeritus komponent - ahelad, mis täidavad osi paralleelprogramm, peate need lohistama üksteisele lähemale, eelistatavalt ühele kristallile. Teisisõnu, üks protsessor peaks organiseerima mitu südamikud, kõiges üksteisega identsed, kuid töötavad iseseisvalt.

Inteli esimesed mitmetuumalised IA-32 protsessorid tutvustati 2005. aastal. Sellest ajast alates on keskmine tuumade arv serveris, töölauas ja praegu mobiilsed platvormid kasvab pidevalt.

Erinevalt kahest ühetuumalised protsessorid Samas süsteemis, jagades ainult mälu, võivad kaks tuuma jagada ka vahemälu ja muid ressursse, mis vastutavad mäluga suhtlemise eest. Enamasti jäävad esimese taseme vahemälud privaatseks (igal tuumal on oma), teine ​​ja kolmas tase võivad olla kas jagatud või eraldi. Selline süsteemikorraldus võimaldab teil vähendada andmeedastuse viivitusi naabertuumade vahel, eriti kui need töötavad ühise ülesande kallal.


Mikrograaf neljatuumalisest Inteli protsessorist koodnimega Nehalem. Üksikud tuumad on esile tõstetud, jagatud vahemälu kolmas tase, samuti QPI lingid teistele protsessoritele ja ühine mälukontroller.

Hüperlõime

Kuni umbes 2002. aastani oli ainus viis saada IA-32 süsteem, mis oleks võimeline paralleelselt töötama kahte või enamat programmi, kasutada mitme protsessoriga süsteeme. Esitati Intel® Pentium® 4 ja Xeoni liin koodnimega Foster (Netburst). uus tehnoloogia- hüperlõime või hüperlõime, - Intel® HyperThreading (edaspidi HT).

Pole midagi uut päikese all. HT on erijuhtum mida kirjanduses nimetatakse samaaegseks multithreadinguks (SMT). Erinevalt “päris” tuumadest, mis on terviklikud ja sõltumatud koopiad, dubleeritakse HT puhul ühes protsessoris ainult osa sisemistest sõlmedest, mis vastutavad peamiselt arhitektuurilise oleku salvestamise eest - registrid. Andmete korraldamise ja töötlemise eest vastutavad täitevsõlmed jäävad ainsuseks ja neid kasutab igal ajahetkel maksimaalselt üks lõimedest. Sarnaselt tuumadega jagavad hüperlõimed vahemälu, kuid mis tasemelt, sõltub konkreetsest süsteemist.

Ma ei püüa selgitada kõiki SMT kujunduste plusse ja miinuseid üldiselt ja HT disainilahendusi konkreetselt. Huviline lugeja leiab tehnoloogia kohta üsna üksikasjaliku arutelu paljudest allikatest ja loomulikult ka Vikipeediast. Siiski märgin ära järgmise olulise punkti, mis selgitab praeguseid piiranguid hüperlõimede arvule päristoodetes.

Lõime piirangud
Millistel juhtudel on "ebaausate" mitmetuumaliste tuumade olemasolu HT kujul õigustatud? Kui üks rakenduse lõim ei suuda kõiki kerneli sees olevaid täitmissõlmi laadida, saab need teisele lõimele laenata. See on tüüpiline rakendustele, millel on kitsaskoht mitte arvutamisel, vaid andmetele juurdepääsul, st tekitavad sageli vahemälu kaotusi ja peavad ootama andmete mälust edastamist. Selle aja jooksul on HT-ta tuum sunnitud tühikäigul töötama. HT olemasolu võimaldab teil kiiresti lülituda vabad täitmissõlmed teisele arhitektuurilisele olekule (kuna see on dubleeritud) ja täita selle juhiseid. See on latentsuspeitmise tehnika erijuht, kui üks pikk toiming, mille jooksul kasulikud ressursid on jõude, on varjatud teiste ülesannete paralleelse täitmisega. Kui rakendusel on juba tuumaressursside kõrge kasutusaste, ei võimalda hüperlõimede olemasolu kiirendamist - siin on vaja "ausaid" tuumasid.

Üldotstarbeliste masinaarhitektuuride jaoks mõeldud töölaua- ja serverirakenduste tüüpilistel stsenaariumidel on HT-ga rakendatud paralleelsuse potentsiaal. See potentsiaal on aga kiiresti ära kasutatud. Võib-olla sel põhjusel ei ületa riistvaraliste hüperlõimede arv peaaegu kõigis IA-32 protsessorites kahte. Tüüpiliste stsenaariumide korral oleks kolme või enama hüperlõime kasutamisest saadav kasu väike, kuid stantsi suuruse, energiatarbimise ja kulude vähenemine on märkimisväärne.

Teistsugust olukorda täheldatakse videokiirendiga tehtavates tüüpilistes ülesannetes. Seetõttu iseloomustab neid arhitektuure suurema arvu lõimedega SMT-tehnoloogia kasutamine. Kuna Intel® Xeon Phi kaasprotsessorid (kasutusele võetud 2010. aastal) on ideoloogiliselt ja genealoogiliselt üsna lähedased videokaartidele, võib neil olla neli hüperkeermestamine igas tuumas – IA-32 jaoks ainulaadne konfiguratsioon.

Loogiline protsessor

Kolmest kirjeldatud paralleelsuse "tasemest" (protsessorid, tuumad, hüperlõimed) võivad teatud süsteemis puududa mõned või isegi kõik. See on mõjutatud BIOS-i sätted(mitmetuumaline ja mitmelõimeline on sõltumatult keelatud), mikroarhitektuuri funktsioonid (näiteks HT puudus Intel® Core™ Duost, kuid see tagastati Nehalemi väljalaskmisel) ja süsteemisündmused (mitme protsessoriga serverid võivad ebaõnnestunud protsessorid välja lülitada kui tõrkeid avastatakse ja jätkake ülejäänud "lendamisega"). Kuidas on see mitmetasandiline samaaegsuse loomaaed operatsioonisüsteemile ja lõpuks rakendusrakendustele nähtav?

Lisaks tähistame mugavuse huvides protsessorite, tuumade ja lõimede arvu teatud süsteemis kolmega ( x, y, z), Kus x on protsessorite arv, y- iga protsessori tuumade arv ja z- hüperlõimede arv igas tuumas. Nüüdsest nimetan seda kolmeks topoloogia- väljakujunenud termin, millel on matemaatika haruga vähe pistmist. Töö lk = xyz määrab kutsutavate üksuste arvu loogilised protsessorid süsteemid. See määratleb paralleelselt käivitavate jagatud mälusüsteemi sõltumatute rakendusprotsessi kontekstide koguarvu operatsioonisüsteem sunnitud arvestama. Ma ütlen "sunnitud", sest see ei saa kontrollida kahe protsessi täitmisjärjekorda erinevatel loogilistel protsessoritel. See kehtib ka hüperlõimede kohta: kuigi need töötavad "järjekorras" samas tuumas, dikteerib konkreetse järjekorra riistvara ja programmid ei saa seda jälgida ega juhtida.

Kõige sagedamini peidab operatsioonisüsteem lõpprakenduste eest selle süsteemi füüsilise topoloogia funktsioone, milles see töötab. Näiteks järgmised kolm topoloogiat: (2, 1, 1), (1, 2, 1) ja (1, 1, 2) – OS esindab neid kahena loogilised protsessorid, kuigi esimesel neist on kaks protsessorit, teisel on kaks südamikku ja kolmandal ainult kaks niiti.


Windows Tegumihaldur näitab 8 loogilist protsessorit; aga kui palju see on protsessorites, tuumades ja hüperlõimedes?


Linuxi top näitab 4 loogilist protsessorit.

See on rakenduste loojatele üsna mugav – nad ei pea tegelema nende jaoks sageli ebaoluliste riistvarafunktsioonidega.

Topoloogia tarkvaraline definitsioon

Muidugi tekitab topoloogia abstraheerimine üheks arvuks loogilisteks protsessoriteks mõnel juhul piisavalt alust segaduseks ja arusaamatusteks (tulistes internetivaidlustes). Arvutusrakendused, mis soovivad riistvarast maksimaalset jõudlust välja pigistada, nõuavad üksikasjalikku kontrolli selle üle, kuhu nende lõimed paigutatakse: külgnevatel hüperlõimedel üksteisele lähemal või vastupidi, erinevatel protsessoritel kaugemal. Sama tuuma või protsessori loogiliste protsessorite vahelise suhtluse kiirus on palju suurem kui protsessorite vahelise andmeedastuse kiirus. Pilti muudab keerulisemaks ka töömälu korralduse heterogeensuse võimalus.

Teave süsteemi kui terviku topoloogia ja iga loogilise protsessori asukoha kohta IA-32-s on saadaval CPUID-juhise abil. Alates esimeste mitmeprotsessoriliste süsteemide tulekust on loogilise protsessori tuvastamise skeemi mitu korda laiendatud. Praeguseks on selle osad CPUID-i lehtedel 1, 4 ja 11. Millist lehte vaadata, saab määrata järgmise artiklist võetud vooskeemi järgi:

Ma ei tüüta teid siin selle algoritmi üksikute osade üksikasjadega. Kui on huvi, võib selle artikli järgmise osa sellele pühendada. Viitan huvitatud lugejale, kes uurib seda küsimust võimalikult üksikasjalikult. Siin kirjeldan kõigepealt lühidalt, mis on APIC ja kuidas see on seotud topoloogiaga. Järgmisena käsitleme tööd lehega 0xB (üksteist tolline kümnend), mis on sisse lülitatud praegu on "apikoehituse" viimane sõna.

APIC ID
Kohalik APIC (täiustatud programmeeritav katkestuskontroller) on seade (nüüd protsessori osa), mis vastutab konkreetsesse loogilisse protsessorisse tulevate katkestuste käitlemise eest. Igal loogilisel protsessoril on oma APIC. Ja igal neist süsteemis peab olema kordumatu APIC ID väärtus. Seda numbrit kasutavad katkestuse kontrollerid adresseerimiseks sõnumite edastamisel ja kõik teised (näiteks operatsioonisüsteem) loogiliste protsessorite tuvastamiseks. Selle katkestuskontrolleri spetsifikatsioonid on arenenud Intel 8259 PIC-st Dual PIC-i, APIC-i ja xAPIC-i kaudu x2APIC-i.

Praegu on APIC ID-s salvestatud numbri laius jõudnud täis 32 bitini, kuigi varem piirdus see 16 ja isegi varem - ainult 8 bitiga. Tänapäeval on vanade aegade jäänused CPUID-s laiali, kuid CPUID.0xB.EDX tagastab kõik APIC ID 32 bitti. Igal loogilisel protsessoril, mis CPUID-käsku iseseisvalt täidab, tagastatakse erinev väärtus.

Perekondlike sidemete selgitamine
APIC ID väärtus ise ei ütle teile topoloogia kohta midagi. Et teada saada, millised kaks loogilist protsessorit asuvad ühes füüsilises protsessoris (st need on “vennad” hüperlõimed), millised kaks on samas protsessoris ja millised on täiesti erinevad protsessorid, tuleb võrrelda nende APIC ID väärtusi. Sõltuvalt suhte astmest langevad mõned nende osad kokku. See teave sisaldub CPUID.0xB alamloendites, mis on ECX-is kodeeritud operandiga. Igaüks neist kirjeldab ühe topoloogiataseme bitivälja asukohta EAX-is (täpsemalt bittide arvu, mida tuleb APIC ID-s paremale nihutada, et eemaldada madalamad tasemed topoloogia), samuti selle kihi tüüp - hüperlõime, tuum või protsessor - ECX-is.

Samas tuumas asuvatel loogilistel protsessoritel on samad APIC ID bitid, välja arvatud need, mis kuuluvad SMT väljale. Samas protsessoris asuvate loogiliste protsessorite puhul kõik bitid, välja arvatud Core ja SMT väljad. Kuna CPUID.0xB alamlehtede arv võib suureneda, see skeem võimaldab edaspidi vajaduse korral toetada topoloogiate kirjeldamist suurema arvu tasemetega. Lisaks on võimalik sisse viia vahepealseid tasemeid olemasolevate vahel.

Selle skeemi korralduse oluline tagajärg on see, et süsteemi kõigi loogiliste protsessorite kõigi APIC ID-de komplektis võivad olla “augud”, s.t. nad ei lähe järjestikku. Näiteks mitmetuumalises protsessoris, mille HT on välja lülitatud, võivad kõik APIC ID-d osutuda paaristeks, kuna hüperlõime numbri kodeerimise eest vastutav vähim bitt on alati null.

Märgin, et CPUID.0xB ei ole ainus operatsioonisüsteemile saadaolevate loogiliste protsessorite teabeallikas. Kõigi talle saadaolevate protsessorite loend koos nende APIC ID väärtustega on kodeeritud MADT ACPI tabelis.

Operatsioonisüsteemid ja topoloogia

Operatsioonisüsteemid pakuvad teavet loogiliste protsessorite topoloogia kohta rakendustele, mis kasutavad oma liideseid.

IN Linuxi teave Topoloogiateave sisaldub pseudofailis /proc/cpuinfo ja ka käsu dmidecode väljundis. Allolevas näites filtreerin cpuinfo sisu mõnes neljatuumalises süsteemis ilma HT-ta, jättes alles ainult topoloogiaga seotud kirjed:

Peidetud tekst

ggg@shadowbox:~$ cat /proc/cpuinfo |grep "protsessor\|füüsiline\ id\|õed\|tuum\|tuumad\|apicid" protsessor: 0 füüsilist id: 0 õde-venda: 4 tuuma id: 0 protsessori südamikku: 2 apitsiid: 0 esialgne apitsiid: 0 protsessor: 1 füüsiline ID: 0 õde-venda: 4 tuuma ID: 0 protsessorituuma: 2 apitsiid: 1 esialgne apitsiid: 1 protsessor: 2 füüsiline ID: 0 õde-venda: 4 tuuma ID: 1 protsessori südamikku: 2 apitsiid: 2 esialgne apitsiid: 2 protsessor: 3 füüsiline ID: 0 õde-venda: 4 tuuma ID: 1 protsessori tuuma: 2 apitsiid: 3 algset apitsiid: 3

FreeBSD-s teatatakse topoloogiast sysctl mehhanismi kaudu muutujas kern.sched.topology_spec XML-ina:

Peidetud tekst

user@host:~$ sysctl kern.sched.topology_spec kern.sched.topology_spec: 0, 1, 2, 3, 4, 5, 6, 7 0, 1, 2, 3, 4, 5, 6, 7 0, 1 grupp THREADSMT grupp 2, 3 grupp THREADSMT grupp 4, 5 grupp THREADSMT grupp 6, 7 grupp THREADSMT grupp

MS Windows 8 puhul saab topoloogiateavet näha tegumihalduris.

See on neljas artikkel sarjast "Breaking the Windows Limits", milles räägin Windowsi põhiressursside piirangutest. Seekord arutlen teiega Windowsi toetatavate lõimede ja protsesside maksimaalse arvu piiranguid. Siin kirjeldan lühidalt lõime ja protsessi erinevust, küsitluse lõime piirangut ning seejärel räägime protsessiga seotud piirangutest. Kõigepealt otsustasin rääkida lõime piirangutest, kuna igal aktiivsel protsessil on vähemalt, ühel lõimel (protsessil, mis on väljunud, kuid mille viide on salvestatud teise protsessi pakutavasse käitlejasse, pole lõime), mistõttu protsessi piirangud sõltuvad otseselt aluseks olevatest lõime piirangutest.

Erinevalt mõnest UNIX-i variandist ei ole enamikul Windowsi ressurssidel operatsioonisüsteemi sisseehitamise ajal fikseeritud limiit, vaid need on piiratud OS-i saadaolevate ressursside põhjal, millest ma varem rääkisin. Näiteks protsessid ja lõimed nõuavad enda jaoks füüsilist mälu, virtuaalmälu ja kogumismälu, nii et protsesside ja lõimede arvu, mida saab antud Windowsi süsteemis luua, määrab lõpuks üks neist ressurssidest, olenevalt sellest, kuidas need protsessid või lõimed loodi ja milline aluseks olevatest ressursipiirangutest saavutatakse esimesena. Seetõttu soovitan teil lugeda minu varasemaid artikleid, kui te pole seda veel teinud, sest järgmisena viitan sellistele mõistetele nagu reserveeritud mälu, eraldatud mälu ja süsteemimälu limiit, millest ma oma eelmistes artiklites rääkisin:

Protsessid ja lõimed
Windowsi protsess on sisuliselt konteiner, mis salvestab käivitatavast failist käsukoodi. See esindab tuuma protsessiobjekti ja Windows kasutab seda protsessiobjekti ja sellega seotud andmestruktuure teabe salvestamiseks ja haldamiseks käivitatav kood rakendusi. Näiteks on protsessil virtuaalne aadressiruum, kuhu salvestatakse selle privaatsed ja avalikud andmed ning kuhu käivitatav pilt ja sellega seotud DLL-id. Windows kasutab diagnostikatööriistu, et salvestada teavet protsessi ressursikasutuse kohta, et aidata taotlusi jälgida ja täita, ning salvestab protsessi viited operatsioonisüsteemi objektidele protsessikäepideme tabelis. Protsessid töötavad turvakontekstiga, mida nimetatakse märgiks, mis tuvastab kasutajakonto, rühma konto ja protsessile määratud õigused.

Protsess sisaldab ühte või mitut lõime, mis tegelikult protsessis koodi käivitavad (tehniliselt ei käita mitte protsessid, vaid lõimed) ja on süsteemis esindatud tuumalõime objektidena. On mitmeid põhjuseid, miks rakendused loovad lõime lisaks algsele alglõimele: 1) kasutajaliidesega protsessid loovad tavaliselt lõime selleks, et oma tööd teha, hoides põhilõime kasutaja sisendkäskude ja aknahalduse suhtes tundlikuna; 2) Rakendused, mis soovivad jõudluse suurendamiseks kasutada mitut protsessorit või soovivad jätkata töötamist ka siis, kui lõimed on seiskunud ja oodanud sisend- ja väljundväljundit sünkroonimist, looge lõime, et kasutada ära mitme lõime.

Lõime piirangud
Lisaks põhiteabele lõime kohta, sealhulgas CPU registrite olek, lõime prioriteet ja teave lõime ressursikasutuse kohta, on igal lõimel eraldatud osa protsessi aadressiruumist, mida nimetatakse virnaks, mida lõime saab kasutada töömälu programmikoodi täitmise ajal funktsiooni parameetrite edastamiseks, kohalike muutujate ja funktsiooni tulemuste aadresside salvestamiseks. Seega, et vältida süsteemi virtuaalmälu raiskamist, eraldatakse algselt vaid osa pinust või kantakse osa sellest lõimele üle ja ülejäänu lihtsalt reserveeritakse. Kui mäluvirnad kasvavad kahanevas järjekorras, asetab süsteem mälu niinimetatud "kaitselehed" väljapoole viru eraldatud osa, mis tagavad, et lisamälu (nn virna laiendamine) eraldatakse vajaduse korral automaatselt. Järgmine illustratsioon näitab, kuidas eraldatud virna ala muutub sügavamaks ja kuidas kaitselehed liiguvad virna laienemisel 32-bitises aadressiruumis.

Käivitatavate kujutiste kaasaskantavad käivitatavad (PE) struktuurid määravad reserveeritud ja lõime virnale algselt eraldatud aadressiruumi hulga. Vaikimisi reserveerib linker 1 MB ja eraldab ühe lehe (4 KB), kuid arendajad saavad neid väärtusi muuta, muutes oma programmiga suhtlemisel PE väärtusi või kutsudes eraldi lõime funktsiooni CreateTread. Käivitusprogrammi sätete vaatamiseks saate kasutada Visual Studioga kaasas olevat utiliiti, näiteks Dumpbin. Siin on Dumpbini käivitamise tulemused suvandiga /headers uue Visual Studio projekti loodud käivitatavas failis:

Numbrite teisendamine alates kuueteistkümnendsüsteem arvutus, näete, et pinu reservi suurus on 1 MB ja eraldatud mäluala on 4 KB; kasutades uus utiliit Sysinternalsist nimega MMap, saate sellele protsessile manustada ja vaadata selle aadressiruumi ning seeläbi näha protsessi algselt eraldatud pinumälu lehte, valvelehte ja ülejäänud reserveeritud pinumälu:

Kuna iga lõim tarbib osa protsessi aadressiruumist, on protsessidel loodud lõimede arvu põhipiirang, mis on võrdne nende aadressiruumi suurusega jagatuna lõime virna suurusega.

32-bitiste voogude piirangud
Isegi kui protsessil poleks üldse koodi ega andmeid ja kogu aadressiruumi saaks kasutada virnade jaoks, võib 32-bitine protsess vaikeaadressiruumiga 2 baiti luua maksimaalselt 2048 lõime. Siin on Testlimiti tulemused, mis töötab 32-bitises Windowsis valikuga -t (lõime loomine), mis kinnitab selle piirangu olemasolu:

Taaskord, kuna osa aadressiruumist oli juba koodi ja esialgse hunniku mälu jaoks ära kasutatud, ei olnud kogu 2 GB lõimevirnade jaoks saadaval, mistõttu loodud lõimede koguarv ei jõudnud teoreetilise 2048 lõime piirini.

Proovisin Testlimiti käivitada lisavõimalus, mis annab rakendusele laiendatud aadressiruumi, lootes, et kui sellele antakse rohkem kui 2 GB aadressiruumi (näiteks 32-bitistes süsteemides, saavutatakse see rakenduse käivitamisel /3GB või /USERVA valikuga alglaadimiseks. ini või samaväärne BCD-suvand Vistas ja hiljem suurendamises), kasutab see seda. 32-bitistele protsessidele eraldatakse 64-bitises Windowsis töötades 4 GB aadressiruumi, seega kui palju lõime saab 64-bitises Windowsis töötav 32-bitine Testlimit luua? Selle põhjal, mida oleme juba arutanud, peaks vastus olema 4096 (4 GB jagatud 1 MB-ga), kuid praktikas on see arv palju väiksem. Siin on 32-bitine Testlimit, mis töötab 64-bitises Windows XP-s:

Selle lahknevuse põhjus seisneb selles, et kui käivitate 32-bitise rakenduse 64-bitises Windowsis, on see tegelikult 64-bitine protsess, mis käivitab 32-bitiste lõimede nimel 64-bitist koodi ja seetõttu on sellel -lõimemälu alad on reserveeritud 64- ja 32-bitiste keermevirnade jaoks. 64-bitise virna jaoks on reserveeritud 256 KB (erandiks on enne Vistat välja antud operatsioonisüsteemid, milles 64-bitiste lõimede esialgne pinu suurus on 1 MB). Kuna iga 32-bitine lõime algab 64-bitises režiimis ja sellele eraldatud virna suurus on käivitamisel suurem kui lehe suurus, näete enamikul juhtudel, et 64-bitise lõime pinu on eraldatud vähemalt 16 Kb. Siin on näide 32-bitise voo 64- ja 32-bitistest virnadest (32-bitine virn on sildiga "Wow64"):

32-bitine Testlimit suutis 64-bitises Windowsis luua 3204 lõime, mis on seletatav asjaoluga, et iga lõim kasutab virna jaoks 1MB + 256KB aadressiruumi (erandiks on jällegi Windowsi versioonid Vistasse, kus kasutatakse 1MB+1MB). 32-bitise Testlimiti käivitamisel 64-bitises Windows 7-s sain aga teistsuguse tulemuse:

Windows XP ja Windows 7 tulemuste erinevused tulenevad Windows Vista aadressiruumi jaotamise skeemi (ASLR) juhuslikumast olemusest, mis põhjustab mõningast killustumist. Juhuslik DLL-i laadimine, lõimede virn ja paigutus dünaamiline mälu, aitab parandada kaitset pahavara eest. Nagu näete järgmises VMMap-programmi hetktõmmises, testimissüsteem Aadressiruumi on veel 357 MB, kuid suurim vaba plokk on 128 KB, mis on vähem kui 32-bitise virna jaoks vajalik 1 MB:

Nagu ma märkisin, saab arendaja vaikeviru reservi suuruse alistada. Üks neist võimalikud põhjused Seda saab teha aadressiruumi raiskamise vältimiseks, kui on ette teada, et lõime virn kasutab alati vähem kui vaikeväärtus 1 MB. Testlimiti PE-kujutis kasutab vaikimisi virna reservi suurust 64 KB ja kui määrate valiku -n koos võtmega -t, loob Testlimit lõime 64 KB pinu suurusega. Siin on selle utiliidi käivitamise tulemus 32-bitise Windows XP ja 256 MB RAM-iga süsteemis (käitsin selle testi spetsiaalselt nõrk süsteem, et seda piirangut rõhutada):

Siinkohal tuleb märkida, et ilmnes veel üks viga, mis tähendab, et antud olukorras ei ole põhjus aadressiruumis. Tegelikult peaksid 64Kb virnad andma ligikaudu 32 000 lõime (2Gb/64Kb = 32768). Niisiis, milline piirang ilmnes sel juhul? Kui vaatate võimalikke kandidaate, sealhulgas eraldatud mälu ja kogumit, ei anna need sellele küsimusele vastuse leidmisel vihjeid, kuna kõik need väärtused on alla nende piiride:

Vastuse leiame siit Lisainformatsioon mälu kohta kerneli siluris, mis näitab meile vajalikku limiiti, mis on seotud saadaoleva püsiva mäluga, mille kogu maht on ammendatud:

Saadaolev püsimälu on füüsiline mälu, mis on eraldatud andmete või koodi jaoks, mis peab asuma RAM-is. Lehitsemata kogumi ja lehitsemata draiverite suurused arvutatakse sõltumatult, nagu ka näiteks RAM-is sisend- ja väljundtoimingute jaoks reserveeritud mälu. Igal lõimel on mõlemad kasutajarežiimi virnad, nagu ma juba rääkisin, kuid neil on ka privilegeeritud režiimi (kerneli režiimi) virn, mida kasutatakse siis, kui lõimed töötavad kerneli režiimis, näiteks käivitavad süsteemikutseid. Kui lõim on aktiivne, kinnitatakse selle kerneli virn mällu, et lõim saaks tuumas käivitada koodi, mille jaoks ei pruugi vajalikud leheküljed puududa.

Põhikerneli virn võtab 32-bitises Windowsis 12 kb ja 64-bitises Windowsis 24 kb. 14225 lõime vajavad umbes 170 MB püsimälu, mis on täpselt nii palju vaba mälu selles süsteemis, kui Testlimit on keelatud:

Kui saadaoleva süsteemimälu limiit on täis, siis paljud põhitoimingud hakkab veaga ebaõnnestuma. Näiteks siin on viga, mille sain otseteel topeltklõpsamisel Internet Explorer asub töölaual:

Ootuspäraselt suutis Testlimit 256 MB RAM-iga 64-bitises Windowsis töötades luua 6600 lõime – umbes poole vähem niite, mida see suutis luua 32-bitises Windowsis 256 MB RAM-iga – enne kui vaba mälu sai otsa:

Põhjus, miks ma varem kasutasin terminit "baas" kerneli virn, on see, et graafika- ja aknafunktsioone täitev lõime saab esimese kõne tegemisel "suure" pinu, mis on võrdne (või suurem) 20 kb 32-bitise kohta. Windows ja 48Kb 64-bitises Windowsis. Testlimiti lõimed ei kutsu ühtegi sellist API-d, seega on neil põhilised kerneli virnad.
64-bitiste voogude piirangud

Sarnaselt 32-bitistele lõimedele on 64-bitistel lõimedel vaikimisi 1 MB virnareserv, kuid 64-bitistel lõimedel on palju rohkem kasutaja aadressiruumi (8 TB), nii et see ei tohiks olla probleem, kui tegemist on suure hulga failide loomisega. niidid. Siiski on selge, et kasutatav mälu on endiselt potentsiaalne piiraja. Testlimiti 64-bitine versioon (Testlimit64.exe) suutis 64-bitise Windows XP ja 256 MB RAM-iga süsteemis luua nii valikuga -n kui ka ilma selleta umbes 6600 lõime, mis on täpselt sama, mis 32-bitine versioon loodud, kuna saavutati residendist saadaoleva mälu limiit. Kuid 2 GB muutmäluga süsteemis suutis Testlimit64 luua ainult 55 000 lõime, mis on oluliselt väiksem lõimede arvust, mida see utiliit võiks luua, kui piirang oleks alaline vaba mälu (2 GB/24 KB = 89 000):

Sel juhul on põhjuseks lõimele eraldatud esialgne pinu, mis põhjustab süsteemi tühjenemise Virtuaalne mälu ja kuvatakse tõrge ebapiisava saalefaili mahu tõttu. Kui eraldatud mälu maht jõuab RAM-i suuruseni, väheneb uute lõimede loomise kiirus märkimisväärselt, kuna süsteem hakkab "libisema", varem loodud lõimevirnasid hakatakse lehitsema lehefaili, et teha ruumi uutele lõimevirnadele, ja lehe fail peab kasvama. Kui suvand -n on sisse lülitatud, on tulemused samad, kuna algne eraldatud pinumälu maht jääb samaks.

Protsessi piirangud
Windowsi toetatud protsesside arv peaks ilmselgelt olema väiksem kui lõimede arv, sest igal protsessil on üks lõime ja protsess ise põhjustab täiendavat ressursikulu. 32-bitine Testlimit, mis töötab 64-bitise Windows XP ja 2 GB süsteemimäluga süsteemis, loob umbes 8400 protsessi:

Kui vaatate kerneli siluri tulemust, saab selgeks, et sel juhul on residentide saadaoleva mälu limiit täis:

Kui protsess peaks kasutama püsivat vaba mälu, et mahutada ainult privilegeeritud režiimi lõime virna, suudaks Testlimit luua 2 GB süsteemis palju rohkem kui 8400 lõime. Selles süsteemis on ilma Testlimiti töötamata 1,9 GB vaba mälumaht:

Jagades Testlimiti kasutatava püsimälu (1,9 GB) loodud protsesside arvuga, leiame, et igal protsessil on 230 KB püsimälu. Kuna 64-bitine kerneli virn võtab enda alla 24 KB, jääb ühe protsessi kohta puudu umbes 206 KB. Kus on ülejäänud kasutatud püsimälu? Protsessi loomisel reserveerib Windows piisavalt füüsilist mälu, et pakkuda minimaalset töötavat lehtede komplekti. Seda tehakse tagamaks, et protsessil oleks igas olukorras piisavalt füüsilist mälu, et salvestada minimaalse töövõimega lehekülgede kogumi loomiseks vajalik hulk andmeid. Vaikimisi on lehtede töökomplekti suurus sageli 200 KB, mida saab hõlpsasti kontrollida, lisades protsessiuurija aknasse veeru Minimaalne töökomplekt:

Ülejäänud 6 Kb on püsivalt juurdepääsetav mälu, mis on eraldatud täiendava mittelehtmälu jaoks (ingliskeelsest mittelehtmälust), kuhu salvestatakse protsess ise. 32-bitise Windowsi protsess kasutab veidi vähem püsimälu, kuna selle lõime privilegeeritud virn on väiksem.

Nagu ka kasutajarežiimi lõimevirnade puhul, saavad protsessid funktsiooni SetProcessWorkingSetSize abil oma töökomplekti vaikesuuruse alistada. Testlimit toetab suvandit -n, mis koos võtmega -p võimaldab määrata lehtede töökomplekti minimaalseks võimalikuks suuruseks 80 Kb põhiprotsessi Testlimiti alamprotsesside jaoks. Kuna alamprotsessid vajavad oma töölehtede komplektide vähendamiseks aega, peatab Testlimit pärast seda, kui see enam protsesse ei tekita, pausi ja proovib käitamist jätkata, andes alamprotsessidele võimaluse käivitada. Testlimitil, mis käivitati parameetriga -n Windows 7 ja 4 GB muutmäluga süsteemis, erineb residendist saadaoleva mälu limiit – eraldatud süsteemimälu limiit:

Alloleval ekraanipildil näete, et kerneli silur ei teata mitte ainult eraldatud süsteemimälu limiidi täitmisest, vaid ka sellest, et pärast selle limiidi saavutamist on ilmnenud tuhandeid mälueraldusvigu, nii virtuaalset kui ka mälu. lehekülgede kogum (eraldatud süsteemimälu limiit saavutati tegelikult mitu korda, kuna lehefaili mahu puudumise tõttu tõrke ilmnemisel suurenes see sama maht, lükates seda limiiti tagasi):

Enne Testlimiti käivitamist oli keskmine mälujaotus umbes 1,5 GB, seega võtsid lõimed umbes 8 GB eraldatud mälu. Seetõttu kulus iga protsessi jaoks ligikaudu 8 GB/6600 või 1,2 MB. Kernel debugger!vm käsu väljund, mis näitab jaotust enda mälu(inglise privaatmälust) iga protsessi jaoks kinnitab selle arvutuse õigsust:

Varem kirjeldatud lõime virnale eraldatud algsel mälumahul on vähe mõju ülejäänud mälu eraldamise taotlustele, mis on vajalikud protsessi aadressiruumi andmestruktuuride, lehe tabeli kirjete, käsitsetabeli kirjete, protsesside ja lõime objektide jaoks ning tema enda andmete jaoks, mis protsess loob selle initsialiseerimise ajal.

Kui paljudest protsessidest ja lõimedest piisab?
Seega on vastused küsimustele "mitu lõime Windows toetab?" ja "mitu protsessi saate Windowsis korraga käivitada?" omavahel seotud. Lisaks nüanssidele, kuidas lõimed määravad nende virna suuruse ja kuidas protsessid määravad nende minimaalse töö lehekülgede komplekti, on kaks peamist tegurit, mis määravad nendele küsimustele vastused mis tahes süsteemis, füüsilise mälu maht ja süsteemimälu eraldamise limiit. Igal juhul, kui rakendus loob nendele piiridele lähenemiseks piisavalt lõime või protsesse, peaks selle arendaja selle rakenduse kujunduse uuesti läbi vaatama, kuna mõistliku protsesside arvuga sama tulemuse saavutamiseks on alati erinevaid viise. Näiteks on rakenduse skaleerimisel põhieesmärk hoida töötavate lõimede arv võrdne protsessorite arvuga ning üks viis selle saavutamiseks on liikuda sünkroonse sisendi/väljundi kasutamiselt asünkroonsele lõpetamisportide kasutamisega, mis peaks aitama hoida töötavate lõimede arv, mis on kooskõlas CPU-de arvuga.

Selles artiklis räägime sellistest teemadest nagu protsessid ja lõimed, protsesside deskriptorid, räägime voogude sünkroniseerimine ja puudutame kõigi lemmikut Windowsi tegumihaldur.

Kogu eksistentsi vältel protsessi selle täitmist saab mitu korda katkestada ja jätkata. Täitmise jätkamiseks protsessi, on vaja taastada selle töökeskkonna seisund. Töökeskkonna olekut kuvatakse registrite ja programmiloenduri oleku, protsessori töörežiimi, failide avamise viidate, lõpetamata I/O operatsioonide info, selle protsessi poolt sooritatud süsteemikõnede veakoodide jms järgi. Seda teavet nimetatakse protsessi kontekst.

Selleks, et OS saaks protsesse hallata, peab sellel olema kogu selleks vajalik teave. Sel eesmärgil algab iga protsess protsessi käepide.

Kirjeldaja – eriline teabe struktuur, mis käivitatakse iga protsessi jaoks (ülesande deskriptor, ülesande juhtplokk).

Üldiselt sisaldab deskriptor järgmist teavet:

  1. Protsessi ID.
  2. Protsessi tüüp (või klass), mis määrab järelevaataja jaoks mõned ressursside varustamise reeglid.
  3. Protsessi prioriteet.
  4. Olekumuutuja, mis määrab, millises olekus protsess on (töötamiseks valmis, töötab, I/O-seadme ootamine jne)
  5. Kaitstud mäluala (või sellise tsooni aadress), kuhu salvestatakse protsessoriregistrite hetkeväärtused, kui protsess katkestatakse ilma oma tööd lõpetamata. Seda teavet nimetatakse ülesande kontekst.
  6. Teave ressursside kohta, mida protsess omab ja/või millel on õigus kasutada (näited failide avamiseks, teave pooleliolevate I/O toimingute kohta jne).
  7. Koht (või selle aadress) teiste protsessidega suhtlemise korraldamiseks.
  8. Käivitusaja parameetrid (aeg, millal protsess peaks olema aktiveeritud, ja selle protseduuri sagedus).
  9. Failihaldussüsteemi puudumisel ülesande aadress kettal selle algolekus ja ketta aadress, kus see RAM-ist maha laaditakse, kui see asendatakse mõne muuga.

Protsessi käepide Võrreldes kontekstiga sisaldab see rohkem operatiivteavet, mis peaks olema protsessiplaneerimise alamsüsteemile hõlpsasti kättesaadav. Protsessi kontekst sisaldab vähem asjakohast teavet ja seda kasutab operatsioonisüsteem alles pärast seda, kui on tehtud otsus katkestatud protsessi jätkamiseks.

Kirjeldajad, asuvad reeglina püsivalt RAM-is, et kiirendada supervisori tööd, kes korraldab need nimekirjadeks (järjekordadeks) ja kuvab protsessi oleku muutused, liigutades vastavat deskriptorit ühest loendist teise.

Iga oleku jaoks (välja arvatud ühe protsessoriga süsteemi käitamisolek) haldab OS vastavas olekus olevate ülesannete loendit. Siiski võib ooteoleku jaoks olla rohkem kui üks loend, kuid ooteoleku võib põhjustada nii palju erinevaid ressursse.

Näiteks võib sisend-/väljundtoimingu lõpuleviimiseks olla sama palju ooteolekuid, kui palju on süsteemis sisend- ja väljundseadmeid.

Protsessid ja lõimed

Multiprogrammeerimise toetamiseks peab OS ise määratlema ja kujundama need sisemised tööüksused, mille vahel protsessor ja muud arvutiressursid jaotatakse. Praegu määratleb enamik operatsioonisüsteeme kahte tüüpi tööühikuid:

  • Protsess(suurem tööühik).
  • Voolu(niit või niit) on väiksem tööüksus, mida protsess nõuab.
  • Kui nad räägivad protsessidest, siis tahavad nad märkida, et OS toetab nende eraldamist: igal protsessil on oma virtuaalne aadressiruum, igale protsessile on määratud oma ressursid - failid, aknad jne. Sellist isoleerimist on vaja ühe protsessi kaitsmiseks teise eest, kuna nad, jagades kõiki arvutussüsteemi ressursse, konkureerivad üksteisega.

Üldiselt protsessid pole lihtsalt üksteisega mingil moel seotud ja võivad isegi kuuluda erinevatele kasutajatele, kes jagavad sama arvuti süsteem. Ehk siis protsesside puhul peab OS neid täiesti mitteseotuks ja sõltumatuks. Sel juhul vastutab OS protsessidevahelise konkurentsi eest ressursside pärast.

Protsesside kiiruse suurendamiseks on võimalik protsessides endis kasutada sisemist paralleelsust. protsessid.

Näiteks võivad mõned rakenduses tehtavad toimingud nõuda üsna palju protsessori kasutamist. Sellisel juhul on kasutaja rakendusega interaktiivselt töötades sunnitud kaua ootama tellitud toimingu sooritamist ega saa rakendust juhtida enne, kui toiming on lõpuni viidud. Selliseid olukordi tuleb üsna sageli ette näiteks suurte piltide töötlemisel graafilistes redaktorites. Kui tarkvara moodulid, mis teeb selliseid pikki toiminguid, tuleks vormistada iseseisvate "alamprotsesside" kujul ( ojad), mida hakatakse täitma paralleelselt teiste “alamprotsessidega”, siis on kasutajal võimalus ühe rakenduse (protsessi) piires teha paralleelselt mitu toimingut.

Eristada saab järgmisi erinevusi niidid protsessidest:

  • Lõimide OS ei tohiks korraldada täisväärtuslikku virtuaalmasinat.
  • Lõimedel ei ole oma ressursse, need arenevad samas virtuaalses aadressiruumis ning saavad kasutada samu faile, virtuaalseid seadmeid ja muid ressursse nagu antud protsess.
  • Ainus asi, mida lõimedel peab olema, on protsessori ressurss. Üheprotsessorilises süsteemis jagavad lõimed üksteisega protsessori aega samamoodi nagu tavalised protsessid, kuid mitme protsessoriga süsteemis saavad need käivituda samaaegselt, kui neil ei teki konkurentsi teistele ressurssidele juurdepääsu tõttu.

Peaasi, mis tagab mitmelõimelisuse, on võimalus teha ühes rakendusprogrammis paralleelselt mitut tüüpi toiminguid. Kuidas seda rakendatakse? tõhus kasutamine CPU ressursse ja ülesannete täitmise koguaeg väheneb.

Näiteks kui lauaprotsessor või tekstitöötlusprogramm, mis on loodud mitme lõimega töötlemise võimalusi silmas pidades, saab kasutaja taotleda oma töölehe ümberarvutamist või mitme dokumendi liitmist ja samal ajal jätkata tabeli täitmist või avada redigeerimiseks järgmine dokument.

WINDOWSI tegumihaldur

Tegumihaldur kuvab teavet programmide ja protsessid täitmine arvutis. Seal saate vaadata ka kõige sagedamini kasutatavaid protsesside jõudluse mõõdikuid.

Tegumihaldur kuvab arvuti jõudluse põhinäitajaid. Töötavate programmide puhul saate vaadata nende olekut ja lõpetada programmid, mis on lakanud reageerimast. Saate vaadata töötavate protsesside aktiivsust kuni 15 parameetri abil, samuti graafikuid ja teavet protsessori ja mälu kasutamise kohta.

Lisaks, kui olete võrguga ühendatud, saate vaadata võrgu olekut ja jõudlusparameetreid. Kui teie arvutiga on ühendatud mitu kasutajat, saate vaadata nende nimesid, ülesandeid, mida nad täidavad, ja saata neile sõnumi.

Vahekaardil Protsessid kuvab teavet arvutis töötavate protsesside kohta: teavet protsessori ja mälu kasutamise, protsesside loenduri ja mõnede muude parameetrite kohta:

Vahekaardil Jõudlus kuvatakse teave deskriptori loenduri ja lõimede ning mäluparameetrite kohta:

Vaja sisse lõime sünkroonimine esineb ainult mitmeprogrammilises OS-is ja on seotud riistvara ja ühiskasutusega teabeallikad arvuti. Sünkroonimine on vajalik võidujooksude (vt allpool) ja ummikseisude vältimiseks lõimede vahel andmete vahetamisel, andmete jagamisel ning protsessorile ja sisend-väljundseadmetele juurdepääsul.

Lõime sünkroonimine ja protsessid seisnevad nende kiiruste koordineerimises, peatades voolu kuni teatud sündmuse toimumiseni ja selle järgneva aktiveerimise selle sündmuse toimumisel.

Sünkroonimisprobleemide tähelepanuta jätmine mitme keermega süsteemis võib põhjustada vale otsusülesandeid või isegi süsteemi krahhi.

Näide . Teatud ettevõtte kliendiandmebaasi pidamise ülesanne.

Igale kliendile antakse eraldi sissekanne andmebaasis, mis sisaldab välju Tellimus ja Makse. Andmebaasi haldav programm on loodud ühe protsessina, millel on mitu lõime, sealhulgas:

  • Lõim A, mis sisestab andmebaasi info klientidelt saadud tellimuste kohta.
  • Lõim B, mis salvestab andmebaasi info klientide arvete tasumiste kohta.

Mõlemad lõimed töötavad koos ühises andmebaasifailis, kasutades sama tüüpi algoritme:

  1. Antud identifikaatoriga kirje lugemine andmebaasifailist kliendi puhvrisse.
  2. Sisestage uus väärtus väljale Tellimus (voo A jaoks) või makse (voo B jaoks).
  3. Tagasta muudetud kirje andmebaasi faili.

Tähistame sammud 1-3 voolu A jaoks kui A1-A3 ja voolu B jaoks kui B1-B3. Oletame, et lõim A värskendab mingil hetkel klienti N käsitleva kirje Tellimuse välja. Selleks loeb ta selle kirje oma puhvrisse (samm A1), muudab Tellimuse välja väärtust (samm A2), kuid ei tee seda. on aega kirje andmebaasi lisada, kuna selle täitmine katkeb näiteks ajalõigu aegumise tõttu.

Oletame, et lõimel B oli vaja sisestada ka sama kliendi N makseteave. Kui saabub lõime B kord, õnnestub see kirje oma puhvrisse lugeda (samm B1) ja välja värskendada Makse(samm B2) ja seejärel katkestatakse. Pange tähele, et voo B puhvris on kirje kliendi N kohta, milles väli Telli on sama, muutumatu tähendusega.

Oluline kontseptsioon protsesside sünkroonimine on programmi "kriitilise osa" mõiste. Kriitiline osa on programmi osa, milles ühiskasutatavatele andmetele juurde pääseb. Võistlustingimuste mõju ressursile kõrvaldamiseks on vaja tagada, et selle ressursiga seotud kriitilises osas oleks igal ajal maksimaalselt üks protsess. Seda tehnikat nimetatakse vastastikuseks välistamiseks.

Lihtsaim viis vastastikuse välistamise jõustamiseks on lubada kriitilises sektsioonis kõik katkestused keelata. See meetod ei sobi aga, kuna on ohtlik usaldada süsteemi juhtima kasutaja protsessi; see võib protsessorit pikka aega hõivata ja kui protsess jookseb kriitilises piirkonnas kokku, jookseb kogu süsteem kokku, sest katkestusi ei lubata kunagi.

Teine võimalus on kasutada blokeerivaid muutujaid. Igal jagatud ressursil on sellega seotud binaarmuutuja, mis võtab väärtuse 1, kui ressurss on vaba (st ükski protsess ei ole praegu selle protsessiga seotud kriitilises jaotises) ja väärtuse 0, kui ressurss on hõivatud. Alloleval joonisel on näidatud fragment protsessialgoritmist, mis kasutab blokeerivat muutujat F(D), et rakendada vastastikust juurdepääsu välistamist jagatud ressursile D. Enne kriitilisse sektsiooni sisenemist kontrollib protsess, kas ressurss D on vaba. Kui see on hõivatud, siis kontrollitakse tsükliliselt, kui see on vaba, siis määratakse muutuja F(D) väärtuseks 0 ja protsess siseneb kriitilisse sektsiooni. Kui protsess on lõpetanud kõik toimingud jagatud ressursiga D, määratakse muutuja F(D) väärtuseks uuesti 1.

Kui kõik protsessid on kirjutatud ülaltoodud kokkuleppeid kasutades, on vastastikune välistamine garanteeritud. Tuleb märkida, et blokeeriva muutuja kontrollimise ja seadistamise toiming peab olema jagamatu. Seda selgitatakse järgmiselt. Oletame, et muutuja kontrollimise tulemusena tuvastas protsess, et ressurss on vaba, kuid kohe pärast seda, ilma et oleks olnud aega muutujat 0-ks seada, see katkestati. Selle peatamise ajal hõivas ressursi teine ​​protsess, sisenes selle kriitilisse sektsiooni, kuid katkestati ka jagatud ressursiga töötamist lõpetamata. Kui juhtimine naasis esimesele protsessile, seadis see ressursivabaks pidades hõivatud märgi ja alustas oma kriitilise osa täitmist. Seega rikuti vastastikuse välistamise põhimõtet, mis võib potentsiaalselt kaasa tuua soovimatuid tagajärgi. Selliste olukordade vältimiseks on soovitatav masina käsusüsteemis olla üks käsk „check-install“ või rakendada süsteem tähendab asjakohased tarkvara primitiivid, mis keelaksid katkestused kogu kontrollimise ja installimise ajal.

Kriitiliste sektsioonide rakendamisel blokeerivate muutujate abil on märkimisväärne puudus: sel ajal, kui üks protsess on kriitilises sektsioonis, käivitab teine ​​protsess, mis nõuab sama ressurssi. rutiinsed tegevused blokeerimismuutuja küsitlemisega, raiskades protsessori aega. Selliste olukordade kõrvaldamiseks saab kasutada nn sündmuste aparaati. Seda tööriista saab kasutada mitte ainult vastastikuse välistamise probleemide lahendamiseks, vaid ka üldisemate protsesside sünkroniseerimise probleemide lahendamiseks. Erinevates operatsioonisüsteemides realiseeritakse sündmuste aparaat omal moel, kuid igal juhul kasutatakse sarnase eesmärgiga süsteemifunktsioone, mida tinglikult nimetatakse WAIT(x) ja POST(x), kus x on mõne identifikaator. sündmus.

Kui ressurss on hõivatud, siis protsess ei teosta tsüklilist pollimist, vaid kutsub süsteemi WAIT(D) funktsiooni, siin D tähistab sündmust, et ressurss D vabaneb Funktsioon WAIT(D) paneb aktiivse protsessi WAITING olekusse. ja teeb oma deskriptoris märke, et protsess ootab sündmust D. Hetkel ressurssi D kasutav protsess käivitab pärast kriitilisest jaotisest väljumist süsteemi funktsiooni POST(D), mille tulemusena opsüsteem skannib ootavate protsesside järjekorda ja paneb sündmust D ootava protsessi olekusse READY .

Protsesside sünkroonimise üldise vahendi pakkus välja Dijkstra, kes tutvustas kaks uut primitiivi. Abstraktsel kujul toimivad need primitiivid, tähisega P ja V, mittenegatiivsete täisarvu muutujatega, mida nimetatakse semaforid. Olgu S selline semafor. Toimingud on määratletud järgmiselt:

V(S): muutuja S suureneb 1 võrra ühe jagamatu tegevusega; toomist, suurendamist ja salvestamist ei saa katkestada ning S-ile ei pääse selle toimingu ajal juurde muud protsessid.

P(S): Võimalusel vähendab S 1 võrra. Kui S=0, siis on võimatu S-i vähendada ja jääda mittenegatiivsete täisarvude väärtuste piirkonda, sel juhul P-operatsiooni kutsuv protsess ootab, kuni see vähenemine saab võimalikuks. Edukas kontrollimine ja vähendamine on samuti jagamatu toiming.

Erijuhul, kui semafor S saab võtta ainult väärtused 0 ja 1, muutub see blokeerivaks muutujaks. P-operatsioon võib viia seda täitva protsessi ooteolekusse, samas kui V-operatsioon võib teatud tingimustel aktiveerida mõne muu protsessi, mille P-operatsioon peatas.

Protsessi ummikseisu

Mitme protsessi paralleelse täitmise korraldamisel on OS-i üheks põhifunktsiooniks ressursside õige jaotamine töötavate protsesside vahel ning protsesside varustamine vastastikuse sünkroonimise ja andmevahetuse vahenditega.

Protsesside paralleelsel täitmisel võib tekkida olukordi, kus kaks või enam protsessi on kogu aeg blokeeritud. Lihtsaim juhtum on siis, kui mõlemad protsessid ootavad teise protsessi poolt hõivatud ressurssi. Selle ootamise tõttu ei saa kumbki protsess täitmist jätkata ja lõpuks vabastada teise protsessi jaoks vajalik ressurss. Seda ummikseisu nimetatakse ummikseisu(surnud lukk) ummiktee, klammerdama või ummikseisu.

Multitegumtöötlussüsteemis öeldakse, et protsess on ummikus, kui see ootab sündmust, mida kunagi ei juhtu.

Ummikseisudest tuleb eristada lihtsad järjekorrad, kuigi mõlemad esinevad ressursside jagamisel ja näevad välimuselt sarnased: protsess on peatatud ja ootab, kuni ressurss vabaneb. Järjekord on aga normaalne ja on omane märk suurest ressursikasutusest, kui päringud saabuvad juhuslikult. See tekib siis, kui ressurss pole hetkel saadaval, kuid mõne aja pärast see vabastatakse ja protsess jätkab täitmist. Ummik on mõnevõrra lahendamatu olukord.

Ummikprobleem hõlmab järgmisi ülesandeid.

  1. ummikseisude vältimine.
  2. ummikseisu äratundmine.
  3. süsteemi taastamine pärast ummikseisu.

Ummikuid saab ära hoida programmide kirjutamise etapis, st programmid tuleb kirjutada nii, et ummik ei saaks tekkida protsesside vastastikuste kiiruste ühegi suhte juures. Seega, kui eelmises näites nõudsid protsess A ja protsess B ressursse samas järjestuses, siis oleks ummikseisu sattumine põhimõtteliselt võimatu. Teist lähenemist ummikseisude ennetamisele nimetatakse dünaamiliseks ja see hõlmab teatud reeglite kasutamist protsessidele ressursside määramisel, näiteks saab ressursse eraldada kindlas järjestuses, mis on ühine kõikidele protsessidele.

Mõnel juhul, kui paljude protsesside vahel tekib ummik, mis kasutavad paljusid ressursse, on ummikseisu tuvastamine mittetriviaalne ülesanne. Ummikseisude tuvastamiseks on olemas ametlikud tarkvarapõhised meetodid, mis põhinevad ressursside eraldamise tabelite ja hõivatud ressursside päringute tabelite säilitamisel. Nende tabelite analüüs võimaldab tuvastada ummikseisu.

Kui tekib ummikseisu olukord, ei ole vaja kõiki blokeeritud protsesse täitmisest eemaldada. Eemaldada saab neist vaid osa, mis vabastab teiste protsesside poolt oodatud ressursid, osa protsesse saab vahetusalasse tagasi saata, osa protsesse saab “tagasi keerata” nn kontrollpunkti, mis salvestab kogu programmi taastamiseks vajaliku info. hukkamine alates see koht. Kontrollpunktid paigutatakse programmi kohtadesse, mille järel võib tekkida ummik.