Suoritussäie (säie; englanniksi säiettä - säiettä) - pienin käsittelyyksikkö, jonka suorittamisen käyttöjärjestelmän ydin voi määrittää . Säikeiden ja prosessien toteutus vaihtelee käyttöjärjestelmien välillä, mutta useimmissa tapauksissa suoritussäie sijaitsee prosessin sisällä. Samassa prosessissa voi olla useita suoritussäikeitä, jotka jakavat resursseja, kuten muistia , kun taas prosessit eivät jaa näitä resursseja. Erityisesti suoritussäikeillä on yhteinen prosessin käskysekvenssi (sen koodi) ja konteksti , muuttujien arvot (prosessorin rekisterit ja puhelupino ), jotka heillä on kulloinkin.
Analogiana prosessin säikeitä voidaan verrata useisiin kokkiin, jotka työskentelevät yhdessä. He kaikki valmistavat samaa ruokaa, lukevat samaa keittokirjaa samalla reseptillä ja noudattavat sen ohjeita, eivätkä kaikki välttämättä lue samalla sivulla.
Yhdellä prosessorilla monisäikeisyys tapahtuu yleensä aikamultipleksoinnilla (kuten moniajossa ): prosessori vaihtaa eri suoritussäikeiden välillä. Tämä kontekstin vaihto tapahtuu yleensä riittävän usein, jotta käyttäjä havaitsee säikeiden tai tehtävien suorittamisen samanaikaisesti. Moniprosessori- ja moniytimisjärjestelmissä säikeet tai tehtävät voivat itse asiassa toimia samanaikaisesti, ja jokainen prosessori tai ydin käsittelee erillistä säiettä tai tehtävää.
Monet nykyaikaiset käyttöjärjestelmät tukevat sekä aikaleikkausta prosessin ajastimesta että moniprosessorisäikeitä. Käyttöjärjestelmän ydin antaa ohjelmoijille mahdollisuuden ohjata suoritussäikeitä järjestelmäkutsuliittymän kautta . Jotkut ytimen toteutukset kutsuvat sitä ytimen säikeeksi , kun taas toiset kutsuvat sitä kevyeksi prosessiksi ( LWP ), joka on erityinen ydinsäietyyppi, jolla on sama tila ja tiedot.
Ohjelmilla voi olla käyttäjätilan suoritussäikeitä, kun säikeitä luodaan ajastimien, signaalien tai muiden menetelmien avulla keskeyttämään suoritus ja luomaan aikaleikkauksia tiettyä tilannetta varten ( Ad hoc ).
Suoritussäikeet eroavat perinteisistä moniajokäyttöjärjestelmän prosesseista siinä, että:
Windows NT :n ja OS/2 :n kaltaisissa järjestelmissä sanotaan olevan "halpoja" säikeitä ja "kalliita" prosesseja. Muissa käyttöjärjestelmissä suoritussäikeiden ja prosessien välinen ero ei ole yhtä suuri, lukuun ottamatta osoitetilan vaihtamisen kustannuksia, joka sisältää assosiatiivisen käännöspuskurin käytön .
Monisäikeisyys, joka on laajalle levinnyt ohjelmointi- ja koodin suoritusmalli, mahdollistaa useiden säikeiden ajamisen yhdessä prosessissa. Nämä suoritussäikeet jakavat prosessin resurssit, mutta voivat toimia myös itsenäisesti. Monisäikeinen ohjelmointimalli tarjoaa kehittäjille kätevän rinnakkaissuorituksen abstraktion. Ehkäpä tekniikan kiinnostavin sovellus on kuitenkin, kun sitä sovelletaan yhteen prosessiin, mikä mahdollistaa sen rinnakkaisen suorittamisen moniprosessorijärjestelmässä .
Tämä monisäikeisen ohjelman etu mahdollistaa sen toiminnan nopeammin tietokonejärjestelmissä, joissa on useita prosessoreita , prosessorissa, jossa on useita ytimiä, tai koneiden ryhmässä , koska ohjelmasäikeet sopivat luonnollisesti prosessien todella rinnakkaiseen suorittamiseen. Tässä tapauksessa ohjelmoijan on oltava erittäin varovainen välttääkseen kilpailuolosuhteita ja muuta epäintuitiivista käyttäytymistä. Jotta dataa voidaan käsitellä oikein, suoritussäikeiden on usein käytävä läpi kohtaamismenettelyn tietojen käsittelemiseksi oikeassa järjestyksessä. Suoritussäikeet saattavat myös tarvita mutexeja (jotka toteutetaan usein semaforeilla ), jotta jaetut tiedot eivät muutu samanaikaisesti tai luetaan muokkausprosessin aikana. Tällaisten primitiivien huolimaton käyttö voi johtaa umpikujaan .
Toinen monisäikeen käyttö, jopa yksiprosessorijärjestelmissä, on sovelluksen kyky vastata syötteeseen. Jos yksisäikeisissä ohjelmissa suorituksen pääsäike on estetty pitkään käynnissä olevan tehtävän suorittamisen vuoksi, koko sovellus voi olla jäädytettynä. Siirtämällä tällaiset pitkäkestoiset tehtävät työsäikeeseen, joka toimii rinnakkain pääsäikeen kanssa, sovellukset voivat jatkaa vastaamista käyttäjän syötteisiin, kun tehtävät ovat käynnissä taustalla. Toisaalta useimmissa tapauksissa monisäikeisyys ei ole ainoa tapa pitää ohjelma reagoivana. Sama voidaan saavuttaa asynkronisella I/O:lla tai signaaleilla UNIXissa. [yksi]
Käyttöjärjestelmät ajoittavat säikeet kahdella tavalla:
1990-luvun loppuun asti työpöytäprosessoreilla ei ollut monisäikeistä tukea, koska säikeiden välinen vaihto oli yleensä hitaampaa kuin täyden prosessin kontekstin vaihtaminen . Sulautetut prosessorit , joilla on korkeammat vaatimukset reaaliaikaiselle käyttäytymiselle , voivat tukea monisäikeistystä vähentämällä säikeiden välillä siirtymiseen kuluvaa aikaa, ehkä varaamalla omistettuja rekisteritiedostoja kullekin suoritussäikeelle yhteisen rekisteritiedoston tallentamisen/palautuksen sijaan. 1990-luvun lopulla ajatus ohjeiden suorittamisesta useista säikeistä samanaikaisesti, eli samanaikainen monisäikeistys, nimeltään Hyper-Threading, saavutti pöytätietokoneet, joissa oli Intel Pentium 4 -prosessori . Sitten se poistettiin Intel Core - ja Core 2 - arkkitehtuuriprosessoreista , mutta se palautettiin myöhemmin Core i7 - arkkitehtuuriin .
Monisäikeisyyden kriitikot väittävät, että säikeiden käytön lisäämisellä on merkittäviä haittoja:
Vaikka suoritussäikeet näyttävät olevan pieni askel pois peräkkäisestä laskennasta, ne ovat itse asiassa valtava harppaus. He luopuvat peräkkäisen laskennan tärkeimmistä ja houkuttelevimmista ominaisuuksista: ymmärrettävyydestä, ennustettavuudesta ja determinismistä. Suoritussäikeet laskennan mallina ovat huomattavan epädeterministisiä, ja tämän epädeterminismin vähentämisestä tulee ohjelmoijan tehtävä. [2]
Prosessi on "raskain" ytimen ajoitusyksikkö. Omat resurssit prosessia varten allokoi käyttöjärjestelmä. Resursseja ovat muisti, tiedostokahvat, pistokkeet, laitekahvat ja ikkunat. Prosessit käyttävät aikajakoista osoiteavaruutta ja resurssitiedostoja vain eksplisiittisten menetelmien, kuten tiedostokuvainten ja jaetun muistin segmenttien, kautta. Prosessit on yleensä esimuunnettu moniajo-suoritustilaan.
Ytimen säikeet ovat ytimen ajoituksen "kevyitä" yksiköitä. Jokaisessa prosessissa on vähintään yksi suorituksen ydinsäie. Jos prosessissa voi olla useita ytimen suoritussäikeitä, ne jakavat saman muisti- ja resurssitiedoston. Jos käyttöjärjestelmän ajastimen suoritusprosessi on etualalla, myös ytimen säikeet ovat etualalla moniajoa. Ydinsäikeillä ei ole omia resursseja lukuun ottamatta kutsupinoa , kopiota suorittimen rekistereistä , mukaan lukien ohjelmalaskuri , ja säikeen paikallista muistia (jos sellainen on). Ydin voi määrittää yhden suoritussäikeen kullekin järjestelmän loogiselle ytimelle (koska jokainen prosessori jakaa itsensä useisiin loogisiin ytimiin, jos se tukee monisäikeistystä, tai tukee vain yhtä loogista ydintä fyysistä ydintä kohden, jos se ei tue monisäikeistystä), tai se voi vaihda estetyt suoritussäikeet. Ytimen säikeet vievät kuitenkin paljon enemmän aikaa kuin käyttäjäsäikeiden vaihtaminen.
Suoritussäikeet toteutetaan joskus kirjastojen käyttäjätilassa , jolloin niitä kutsutaan suorituksen käyttäjäsäikeiksi . Ydin ei tiedä niistä, joten niitä hallitaan ja ajoitetaan käyttäjätilassa. Joissakin toteutuksissa käyttäjän suoritussäikeet perustuvat suorituksen muutamaan ylimpään ydinsäikeeseen, jotta voidaan hyödyntää moniprosessorikoneita (M:N-mallit). Tässä artikkelissa termi "säie" tarkoittaa oletuksena (ilman "ydintä" tai "mukautettua" tarkennetta) "ytimen säiettä". Virtuaalikoneiden avulla toteutettuja käyttäjäsäikeitä kutsutaan myös "vihreiksi suoritussäikeiksi". Mukautetut suoritussäikeet ovat yleensä nopeita luoda ja helppo hallita, mutta ne eivät voi hyödyntää monisäikeistä ja moniprosessointia. Ne voivat estää, jos kaikki siihen liittyvät ytimen säikeet ovat varattuja, vaikka jotkut käyttäjäsäikeet olisivat valmiita suoritettavaksi.
Kuidut ovat vieläkin "kevyempiä" yhteistoiminnalliseen multitaskingiin liittyviä aikataulutusyksiköitä : käynnissä olevan kuidun on nimenomaisesti "luovutettava" suoritusoikeus muille kuiduille, mikä tekee niiden toteuttamisesta paljon helpompaa kuin ydinsäikeiden tai käyttäjäsäikeiden toteuttaminen. Kuidut voidaan ajoittaa toimimaan missä tahansa suoritussäikeessä samassa prosessissa. Tämän ansiosta sovellukset voivat parantaa suorituskykyä hallitsemalla omaa aikatauluaan sen sijaan, että luottaisivat ytimen ajoittimeen (jota ei ehkä ole määritetty tekemään niin). Rinnakkaisohjelmointiympäristöt, kuten OpenMP , toteuttavat tehtävänsä yleensä kuitujen kautta.
Saman prosessin suoritussäikeillä on sama osoiteavaruus. Tämä mahdollistaa samanaikaisesti suoritettavien koodien tiiviin kytkemisen ja tiedonvaihdon kätevästi ilman ylimääräistä ja monimutkaista prosessien välistä viestintää . Kun useat säikeet jakavat jopa yksinkertaisia tietorakenteita, on olemassa kilpailutilanteen vaara, jos tietojen päivittämiseen tarvitaan useampi kuin yksi prosessoriohje: kaksi suoritussäiettä voi päätyä yrittämään päivittää tietorakenteita samanaikaisesti ja päätyä tiedot, joiden tila poikkeaa odotetusta. Kilpailuolosuhteiden aiheuttamia virheitä voi olla erittäin vaikea toistaa ja eristää.
Tämän välttämiseksi suoritussovellusohjelmointirajapintojen säikeet (API) tarjoavat synkronointiprimitiivit , kuten mutexet , estämään tietorakenteiden samanaikaisen käytön. Yksiprosessorijärjestelmissä lukittuun mutexiin pääsevän säikeen on lopetettava toiminta ja siksi aloitettava kontekstin vaihto. Moniprosessorijärjestelmissä suoritussäie voi saada spinlockin mutexin pollaamisen sijaan . Molemmat menetelmät voivat heikentää suorituskykyä ja pakottaa SMP-järjestelmien prosessorin kilpailemaan muistiväylästä, varsinkin jos lukitusmodulaarisuuden taso on liian korkea.
I/O ja ajoitusRäätälöityjen säikeiden ja kuitujen toteutus tehdään yleensä kokonaan käyttäjätilassa. Tämän seurauksena kontekstin vaihtaminen käyttäjäsäikeiden ja kuitujen välillä samassa prosessissa on erittäin tehokasta, koska se ei vaadi lainkaan vuorovaikutusta ytimen kanssa. Kontekstin vaihto suoritetaan paikallisesti tallentamalla käynnissä olevan käyttäjäsäikeen tai kuidun käyttämät prosessorirekisterit ja lataamalla sitten uuden suorituksen edellyttämät rekisterit. Koska ajoitus tapahtuu käyttäjätilassa, ajoituspolitiikka voidaan helposti räätälöidä tietyn ohjelman vaatimuksiin.
Järjestelmäkutsulukkojen käytössä käyttäjäsäikeissä (toisin kuin ytimen säikeissä) ja kuiduissa on kuitenkin omat ongelmansa. Jos käyttäjäsäie tai kuitu suorittaa järjestelmäkutsun, muut prosessin säikeet ja kuidut eivät voi toimia ennen kuin käsittely on valmis. Tyypillinen esimerkki tällaisesta ongelmasta liittyy I/O-toimintojen suorituskykyyn. Useimmat ohjelmat on suunniteltu suorittamaan I/O synkronisesti. Kun I/O aloitetaan, järjestelmäkutsu tehdään, eikä se palaa ennen kuin se on valmis. Tällä välin ydin estää koko prosessin, eikä sitä voida suorittaa, mikä tekee prosessin muista käyttäjäsäikeistä ja kuiduista toimintakelvottomia.
Yleinen ratkaisu tähän ongelmaan on tarjota erillinen I/O API, joka toteuttaa synkronisen rajapinnan käyttämällä sisäistä estämätöntä I/O:ta, ja käynnistää toinen käyttäjäsäie tai kuitu I/O:n käsittelyn aikana. Samanlaisia ratkaisuja voidaan tarjota järjestelmäpuheluiden estämiseen. Lisäksi ohjelma voidaan kirjoittaa siten, että vältytään käyttämästä synkronisia I/O- tai muita estäviä järjestelmäkutsuja.
SunOS 4.x esitteli niin sanotut " kevyt prosessit " tai LWP:t . NetBSD 2.x + ja DragonFly BSD toteuttivat LWP:n ydinsäikeinä (1:1 malli). SunOS 5.2 ja jopa SunOS 5.8 ja NetBSD 2 ja jopa NetBSD 4 toteuttivat kaksitasoisen mallin käyttämällä yhtä tai useampaa käyttäjäsäiettä ydinsäiettä kohti (M:N malli). SunOS 5.9 ja uudemmat sekä NetBSD 5 poistivat tuen käyttäjäsäikeiltä ja palasivat 1:1-malliin. [3] FreeBSD 5 toteutti M:N-mallin. FreeBSD 6 tukee sekä 1:1- että M:N-malleja, ja käyttäjä voi valita, kumpaa käyttää tietyssä ohjelmassa /etc/libmap.conf-tiedoston avulla. FreeBSD-versiossa 7 1:1-mallista on tullut oletusarvo, ja FreeBSD 8:ssa ja uudemmissa M:N-mallia ei tueta ollenkaan.
Ytimen säikeiden käyttäminen yksinkertaistaa käyttäjäkoodia siirtämällä joitain monisäikeisyyden monimutkaisempia puolia ytimeen. Ohjelmaa ei vaadita ajoittamaan suoritussäikeitä ja suorittimen kaappauksia. Käyttäjäkoodi voidaan kirjoittaa tutulla proseduurityylillä, mukaan lukien API-kutsujen estäminen, ilman, että muiden säikeiden pääsy prosessoriin estetään. Ytimen säikeet voivat kuitenkin aiheuttaa kontekstin vaihdon suoritussäikeiden välillä milloin tahansa ja siten paljastaa kilpailu- ja samanaikaisuusvirheitä, joita ei välttämättä tapahdu. SMP-järjestelmissä tämä on vieläkin pahentunut, koska ytimen säikeet voivat kirjaimellisesti ajaa samanaikaisesti eri prosessoreissa.
Käyttäjän 1-1-mallissa luomat suoritussäikeet vastaavat lähetettäviä ydinkokonaisuuksia. Tämä on yksinkertaisin mahdollinen ketjutuksen toteutus. Windows API on noudattanut tätä lähestymistapaa alusta alkaen . Linuxissa tavallinen C-kirjasto toteuttaa tämän lähestymistavan ( POSIX Thread Libraryn kautta ja vanhemmissa versioissa LinuxThreadsin kautta ). Samaa lähestymistapaa käyttävät Solaris OS , NetBSD ja FreeBSD .
N:1-malli olettaa, että kaikki käyttäjätason suoritussäikeet liittyvät yhteen ydintason ajoituskokonaisuuteen, eikä ydin tiedä mitään sovellussäikeiden koostumuksesta. Tällä lähestymistavalla kontekstin vaihto voidaan tehdä erittäin nopeasti, ja lisäksi se voidaan toteuttaa jopa yksinkertaisissa ytimissä, jotka eivät tue monisäikeistystä. Yksi sen suurimmista haitoista on kuitenkin se, että se ei voi hyödyntää monisäikeisten prosessorien tai moniprosessoritietokoneiden laitteistokiihdytystä, koska vain yksi suoritussäie voidaan ajoittaa kullekin ajankohtana. Tätä mallia käytetään GNU Portable Threads -säikeissä.
M:N-mallissa noin M määrä sovellussäikeitä on kuvattu joillekin N määrälle ydinyksiköitä tai "virtuaaliprosessoreja". Malli on kompromissi ydintason ("1:1") mallin ja käyttäjätason ("N:1") mallin välillä. Yleisesti ottaen "M:N"-järjestelmän ketjuttaminen on monimutkaisempaa toteuttaa kuin ytimen tai käyttäjän suorituksen säikeet, koska koodimuutoksia ei vaadita ytimeen tai käyttäjätilaan. M:N-toteutuksessa säiekirjasto on vastuussa käytettävissä olevien ajoitusolioiden suoritussäikeiden ajoittamisesta. Samalla säikeen kontekstin vaihto tapahtuu erittäin nopeasti, koska malli välttää järjestelmäkutsut. Kuitenkin monimutkaisuus ja prioriteettien inversioiden todennäköisyys lisääntyvät, samoin kuin epäoptimaalinen ajoitus ilman laajaa (ja kallista) koordinointia käyttäjän ajoittimen ja ytimen ajoittimen välillä.
On olemassa monia erilaisia, yhteensopimattomia suorituksia. Näitä ovat sekä ydintason toteutukset että käyttäjätason toteutukset. Useimmiten ne noudattavat enemmän tai vähemmän läheisesti POSIX Threads -liitäntästandardia .
Kuituja voidaan toteuttaa ilman käyttöjärjestelmän tukea, vaikka jotkin käyttöjärjestelmät ja kirjastot tarjoavat niille selkeän tuen.
Monet ohjelmointikielet tukevat säikeitä eri tavalla. Useimmat C- ja C++-toteutukset (ennen C++11-standardia) eivät tarjoa suoraa tukea säikeille itselleen, mutta tarjoavat pääsyn käyttöjärjestelmän tarjoamiin säikeisiin API :n kautta . Jotkut korkeamman tason (yleensä monialustaiset) ohjelmointikielet, kuten Java , Python ja .NET , tarjoavat kehittäjälle ketjutuksen abstraktina, alustakohtaisena, erillään kehittäjän ajonaikaisesta säikeiden toteutuksesta. Useat muut ohjelmointikielet yrittävät myös poistaa täysin samanaikaisuuden ja ketjutuksen käsitteen kehittäjältä ( Cilk , OpenMP , MPI ...). Jotkut kielet on suunniteltu erityisesti samanaikaisuutta varten (Ateji PX, CUDA ).
Jotkut tulkitsevat ohjelmointikielet, kuten Ruby ja CPython (Pythonin toteutus), tukevat säikeitä, mutta niillä on rajoitus, joka tunnetaan nimellä Global Interpreter Lock (GIL). GIL on tulkin suorittama poikkeusmutex, joka voi estää tulkkia tulkitsemasta samanaikaisesti sovelluskoodia kahdessa tai useammassa säikeessä samanaikaisesti, mikä rajoittaa tehokkaasti samanaikaisuutta moniytimisissä järjestelmissä (pääasiassa prosessoriin sidotuille säikeille, ei verkkoon sidotuille säikeille ).).
Käyttöjärjestelmien näkökohdat | |||||
---|---|---|---|---|---|
| |||||
Tyypit |
| ||||
Nucleus |
| ||||
Prosessien hallinta |
| ||||
Muistinhallinta ja osoitus |
| ||||
Lataus- ja alustustyökalut | |||||
kuori | |||||
Muut | |||||
Luokka Wikimedia Commons Wikikirjat Wikisanakirja |