SIMD

**SIMD** (ing k *[[:en:Single_instruction,_multiple_data|single instruction, multiple data]]*) on arvutiarhitektuur, mis võimaldab sarnaseid tehteid läbi viia korraga mitmel andmeblokil. See arhitektuur on üldiselt osa arvutiriistvarast (protsessoril). Tavaliselt toimub tehete teostamine vektori sarnaste andmestruktuuridega: soovitud andmed jagatakse n-pikkustesse andmestruktuuridesse, millega tegeletakse korraga, ning protsessi korratakse kuni kõik andmed on töödeldud. See võimaldab lihtsaid aritmeetilisi tehteid teostada kiiremini kui ilma SIMD-arhitektuuriga protsessorites. 

SIMD käsud on kasulik juhul, kui suurel hulgal andmetel on vaja teostada kas lihtsat aritmeetilist tehte (liitmine, lahutamine, korrutamine, jagamine), või selle sarnast protsessi (absoluutväärtuse võtmine, juurimine jne). Selleks on näiteks audio või pilditöötlus. Uuematel graafikakaartidel on tihti peal SIMD arhitektuur, võimaldamaks korraga töödelda väga suuri andmeblokke.

## Ajalugu
Lühendi SIMD võttis kõnealuses tähenduses esimesena kasutusele Michael J. Flynn oma arvuti arhitektuuri klassifikatsioonides, tuntud ka kui Flynni klassifikatsioonid (Flynn's taxonomy), aastal 1966. Oma klassifikatsioonides kategoriseeris ta arhitektuure vastavalt selle käskude ja kättesaadaval olevate andmete arvule. Neli väljapakutud kategooriat on järgmised: 
***SISD (''Single Instruction stream, Single Data stream'')**: See arhitektuur vastab "üksikprotsessorile" või skalaarprotsessorile, mis käivitab programme järjestikku. Iga käsk töötab ühe käsutsükli jooksul ühe andmega. 
***SIMD (''Single Instruction stream, Multiple Data stream'')**: SIMD arhitektuuri näidete hulka kuuluvad vektorprotsessorid ja GPU-d. SIMD-s täidetakse ühte käsku korraga suurel hulgal andmetel. 
***MISD (''Multiple Instruction stream, Single Data stream'')**: Kommertsprotsessorid järgivad harva MISD-i arhitektuuri. Flynn kirjeldas MISD-protsessoreid kui selliseid, mis kasutavad spetsiaalseid voogedastusorganisatsioone, millel on mitu käsuvoogu ühel andmejadal. 
***MIMD (''Multiple Instruction stream, Multiple Data stream'')**: Kaasaegsed mitmetuumalised protsessorid kuuluvad MIMD arhitektuuri alla. Need sisaldavad paralleelseid funktsionaalseid üksusi, mis toovad ja täidavad sõltumatult erinevatel andmeelementidel mitut käsku. MIMD protsessorid saavad kasutada "Thread Level Paralleelismi" mitme lõimega programmides ja neid on ka superarvutite klastrites. 

SIMD käskude esmakordne kasutamine toimus ILLIAC IV-s, mis valmis 1966. aastal. 

### Vektori superarvutid ja Cray mõju:
1970. ja 1980. aastatel populariseeris Cray Research vektortöötlusarhitektuure. Nende superarvutid, nagu Cray-1, kasutasid SIMD põhimõtteid. Nendel masinatel olid spetsiaalsed vektorkonveierid, mis olid võimelised sooritama aritmeetilisi toiminguid tervete andmevektoritega või massiividega. Vektoritöötlusarhitektuure peetakse tänapäeval SIMD-arvutitest eraldiseisvaks. 

### Kaasaegne SIMD-arhitektuur:

Kaasaegsete SIMD-arvutite algfaasi iseloomustasid superarvutid, mis kasutasid massiliselt paralleelset töötlemist, nagu Mõtlemismasinad CM-1 ja CM-2 (Connection Machine). Need masinad kasutasid mitmeid piiratud funktsionaalsusega protsessoreid, mis töötasid samaaegselt. Nad suutsid loogiliselt kombineerida bitipaare. Superarvuti nihkus puhtalt SIMD-lt eemale, kui tulid kasutusele võimsamad ja kuluefektiivsemad skalaar-MIMD-meetodid. 

### Liikumine koduarvutitesse:
SIMD leidis endale uue koha laua- ja sülearvutites. Tänapäeval kasutatakse SIMD käske rohkem kaasaegsetes protsessorites ja GPU-des. SIMD käsud võimaldavad isiklikes arvutites reaalajas videoid kuvada, pilte töödelda ning teaduslike arvutusi, simulatsioone ja graafikuid koostada. Et neid enam superarvutites nii tihti ei kasutata, on koduarvutitest saanud SIMD arhitektuuri ellujäämise võimalus.  

## Flynni klassifikatsioonid: SIMD
Flynni klassifikatsioonide järgi kuuluvad SIMD klassi protsessorite arhitektuuri alla nii massiiv- kui ka vektorprotsessorid. SIMD protsessorid teevad arvutusi andmestruktuuridel nagu maatriksid ja vektorid. Nende struktuuridega tehakse palju teaduslikke arvutusi ja simulatsioone, mistõttu on SIMD arhitektuur selles valdkonnas laialdaselt levinud. Olemuselt on SIMD arhitektuurile kirjutatud programmis siiski sarnased skalaarprotsessori omadega. 
### Massiiviprotsessoris
Massiiviprotsessor koosneb mitmest protsessori elemendist, mis on omavahel ühendatud ühe või mitme võrguga. Need võrgud saavad olla nii globaalseks kui kohalikuks suhtluseks ning juhtimiseks. Protsessori elemendid omavad oma lokaalset mälu. Otsejuurdepääs globaalsele mälule või mõne teise protsessori elemendi mälule on keeruline. Selle asemel liigutatakse andmeid elementide vahel nende vaheliste ühenduste kaudu. Andmed jaotatakse korrapäraselt nende mälude vahel olenevalt nii andmete tegelikust struktuurist kui ka neile teostatavatest käskudest. Et andmeid saaks protsessori elementide vahel korrapäraselt liigutada ning et nende kindlate marssruutide arvutamine oleks lihtsam, tuleb andmed jaotada hoolikalt. Siiski, võib tulla ette, et parem on elemente liigutamise asemel hoopis dubleerida. 

Käskude edastamise ajal ei ole üksikutel protsessori elementidel võimalik käsuvood muuta. Samas saavad nad tinglikult käskude täitmise lokaalselt välja lülitada vastavalt enda olekule - kindlatel tingimustel on vastaval need protsessori elemendid seisatud. Käskude teostamine käib tavaliselt massiiviprotsessoris, mis on ühendatud SISD üldotstarbelise protsessoriga. SISD protsessor teostab skalaarseid arvutusi ning väljastab massiivioperatsioone. Need edastatakse massiivi kõikidele protsessori elementidele. Juhtprotsessori ülesanne on täita rakenduse arvutuslikke osi, liidestada programmi välismaailmaga ning juhtida käskude täitmise voogu, massiiviprotsessor täidab rakenduse massiivi osi juhtprotsessori juhiste järgi.  

Massiiviprotsessori programmeerimisel tuleb tegeleda programmeerijal andmete ja arvutuste vaheliste suhete kirjeldamisega. Siiski ei ole vajadust kirjeldada üksikasju skalaar- ja massiivikäskude ajastamiseks ega andmete erinevate protsessori elementide vahel jaotamiseks. Ka massiiviprotsessori reaalse suurusega ei ole tegelikult tihti vaja arvestada, sest arvuti suudab vastavalt suurustele iseseisvalt toimida. Programmeerija peab määrama andmete suuruse ja mistahes spetsiifilise jaotuse eeskirjad ning kompilaator kaardistab vastaval sellele kaudse virtuaalse protsessori massiivi olemasolevatele füüsilisetele protsessori elementidele ning genereerib koodi vajalike arvutuste tegemiseks.   
### Vektorprotsessoris
Vektorprotsessor on üks protsessor, mis meenutab traditsioonilist SISD-protsessorit, kuid mõned funktsionaalsed üksused (ja registrid) töötavad vektoritel. Need funktsionaalsed üksused on omavahel konveieritega tihedalt seotud ning neil on kõrge taktsagedus. Vektorkonveieritel on pikem latentsusaeg kui tavalistel skalaarfunktsiooni üksustel, aga tänu nende kõrgele taktsagedusele ning suurele vektori sisesele andmete edastamise kiirusele on neil märkimisväärne läbilaskevõime, mis ei oleks saavutatav skalaarfunktsiooni üksusega. Varajaste vektorprotsessorite puhul töödeldi vektoreid otse mälus. Selle lähenemisviisi peamine eelis oli see, et vektorite suurused ei olnud limiteeritud ning neid ei piiranud protsessori registrid ega ressursid. Siiski oli selline lähenemine kõrge käivituskuluga ning samuti osutus piiranguks mälusüsteemi ribalaius. 

Kaasaegsed vektorprotsessorid nõuavad, et vektorid paigutatakse spetsiaalsetesse vektorregistritesse ja salvestataks nendest registritest tagasi mällu. Vektorregistri fail koosneb mitmest vektorregistrite komplektist (igas komplektis võib-olla 64 registrit). Vektorprotsessoritel on kõrge jõudluse pakkumiseks mitmeid spetsiaalseid funktsioone. Üks nendest lubab salvestada ja laadida andmeid registrite ja mälude vahel ning samal ajal teostada arvutusi vektorregistrite andmetega. See on oluline, sest vektorprotsessoris on vaja vektoreid töödelda segmentidena. Kui mälu poole pöördumine ja sinna andmete üles laadimine peaks toimuma eraldi arvutuste teostamisest, tekkiks suurte andmehulkade puhul pikad ooteajad andmete liigutamise ja töötlemise vahele ning sellest kujuneks pudelikael. Nagu ka SISD protsessorite puhul, on vektorprotsessorites võimalik vahetulemusetel ligi saada arvutuste keskel, seda nimetatakse antud juhul aheldamiseks. See võimaldab vahetulemustega arvutusi jätkata samal ajal, kui mujal veel teostatakse algseid arvutusi. Nii ei pea programm ootama, et terve vektoriga üks arvutus tehtud saaks - nii, kui vahetulemus on saadaval, saab minna edasi, ja sellest tulenevalt toimuvad tihti mitme erisammu käskude teostamine peaaegu samaaegselt. Järjestikuseid arvutusi saab tõhusalt liita ja need toimivad nii, nagu oleks tegemist ühe operatsiooniga. 

Programmeerides vektorprotsessorit näeb programmeerija enamasti traditsioonilist SISD-masinat; aga kuna vektormasinad on suurepärased vektoriseeritavate tsüklitega, saab programmeerija sageli rakenduse jõudlust parandada, kui spetsiifiliselt välja kirjutada, kuidas registreid omavahel kattuma panna ja aheldada ning andes kompilaatorile vihjeid leidmaks parimaid viise vektoriseeritavade osade leidmiseks. Et programmeerija elu kergendada, on loodud eraldi keeled (nt Fortran 90 või High-Performance Fortran), mida kasutades peab vähem kokku puutuma arvuti üksikasjadega ning selle SIMD olemusega.  

## Andmetöötlus ja selle eelised

Nagu mainitud, on SIMD käsud kasulikud lihtsate aritmeetiliste tehete teostamiseks, mida tuleb palju ette erinevate multimeedia rakendustes. Näiteks kiirendab see pildi ereduse muutmist. Värvilisel ekraanil kuvatud pildid koosnevad kolmest väärtusest: R (punane), G (roheline), B (sinine). Need määravad selle värvi osakaalu pikslil. Soovides pildi eredust muuta, tuleb igale sellele väärtusele iga piksli puhul liita (või sellest lahutada) kindel arv. Seda on võimalik teha ükshaaval, liigutades andmeid piksli kaupa ning teostades tehteid teineteise järel. Nii aga on protsess aeganõudev.  

SIMD käsud võimaldavad protsessi kiirendada kahel viisil. Esiteks saab andmeid kohelda plokkidena (vektoritena). Korraga saab paluda, et vaadeldakse mingit n-arvulist plokki (n-i väärtus oleneb spetsiifilisest SIMD arhitektuurist), ning neid andmeid korraga liigutada. See võimaldab maksimaalselt ära kasutada protsessoris olevat andmesiini. Näiteks, kui protsessori registrisse mahuks 32 bitti ja pikslite väärtuse salvestamiseks on kasutatud 8 bitti, siis SIMD käsud võimaldavad korraga teostada arvutusi 4 arvuga. Teiseks saab tehteid teostada paralleelselt, vähendades nii suurte andmehulkade puhul arvutusaega massiivselt.  

Lisaks multimeediale on SIMD käsud leidnud laialdast rakendust ka masinõppes ja tehisintellektis. Masinõppe jaoks on vaja teostada mitmeid arvutusi suurte maatriksitega. Neid arvutusi on võimalik paralleelse andmetöötlusega suuresti kiirendada. Samuti on kasu sellest ka pildituvastusel ning suurte andmehulkade töötlusel ja analüüsil. SIMD käsud on masinõppe asendamatu tööriist. 

## Programmeerimine
Kuna arvutid ei ole üldjoontes võimelised C-keeles kirjutatud programme automaalselt implementeerima SIMD käskudesse, tuleb programm juba vastavalt luua. SIMD käskude kirjutamisel tuleb lähtuda vastavatest andmetüüpidest ja limitatsioonidest. SIMD arhitektuuris käsitletakse vektorid. Seega tuleb klassiklaliste andmetüüpide asemel kasutada neile vastavaid vektori tüüpe. Tabelis 1.1 on toodud vektortüübid ning nendele vastavad klassikalised andmetüübid. Tabel on inglikeelsete tüüpidega:

Kui arvutile on märku antud, kuidas andmed vektoriteks jaotada, on edasine programmeerimine väga sarnane SISD (Single Instruction, Single Data) programmidele. Eraldi võib vaja minna spetsifeerida, millises järjekorras andmed vektoritesse on jagatud või kuidas vektorite ja skalaaride vahel teisendused toimuvad. Samuti tuleb eraldi kasutada vektoritele vastavaid aritmeetika käske (liitmine: vec_add(a,b), lahutamine_ vec_sub(a,b) jne). Programmide peaksid kompileeruma samamoodi nagu C-keele programmid.

## Viited