Pereiti prie turinio

Spekuliacijos

Iš Wikibooks.

Spekuliacijos apie tai kas renderina video žaidimuose grafiką

[keisti]
Sovietiškai mąstantys žmonės labiau linkę tikėti, kad 3D grafiką žaidimuose galėtų renderinti ne GPU, bet CPU. O GPU galėtų tik išvesti paveiksliuką, kuri perduoda CPU į GPU RAM'us. Savo ruožtu GPU ima gatavą paveiksliuką iš GPU VRAM (Video RAM) ir kas pirmesnis deda ar ima (CPU ar GPU), tam ir priegos prie VRAM pirmenybė (GPU tą paveiksliuką-bitmap'ą išveda į monitorių).
Dar galėtų CPU neturėti jokių core'ių, bet veikti didesniu dažniu, o Core'ius naudojančios programos veikia lėčiau nei vienam Core'iu skirtos senos programos... Bet tada CPU turėtų veikti apie 10 ar 100 kartu didesniu dažniu, nei oficialiai laikoma, nes kitaip neužtektų CPU resursu ir galingumo (net jei RAM veiktų tokiu pat dažniu kaip CPU ir be jokių latency stabdžių), kad nurenderinti tokio sudetingumo scenas ir vaizdus kaip yra šiuolaikiniuose žaidimuose.


Kitas variantas yra, kad GPU turi kažkokius specializuotus tipo core'ius, skaičiumi nuo 20 iki 100 ir jie kiekvienas renderina suskaidytos į stačiakampius scenos gabaliuką. Pavyzdžiui, jeigu yra 100 tų GPU core'ių viename GPU, tai rezoliucija 1920*1080 suskaidoma į 100 stačiakampių rezoliucijos 192*108 ir kiekvienas GPU core renderina atskirai kiekvieną mažą stačiakampį ir naudoja tą pačią (arba skirtingą) VRAM atmintį, nes kadangi visi core'iai dažniausiai buna užimti tai kova ir laukimas paėmimo iš atminties (ar įdėjimo į VRAM) būna ne toks tragiškas. Bet kuo daugiau core'ių, tuo mažesnis efektyvumas. Atmintis galėtų būti 32 bitų interface'o arba 64 bitų arba 128 bitų (kas gerai tinka 32 bitų 3 spalvom [raudona, žalia, mėlyna] ir alpha [permatomumo lygis] arba 3D objektų trikampių verteksų 3 koordinatėms ir dar 32 bitai kam nors). Šiaip viena spalva užima 8 bitus, bet kai paverčiama visokiems HDR skaičiavimas ir kitiems žaidimams su spalvom ir spalvu sudėtim bei apšvietimo efektams, tai reikia, kad butų daugiau bitų vienai spalvai ir su slankaus kablelio [single precision] formate. Tai tokie vektoriai galėtų būti apdorojami iki 4 kartų greičiau nei 32 bitų VRAM data bus.


Kaip galima paaiškint, kad didesnėje renderinimo rezoliucijoje kadrai per sekunde (FPS) daug labiau priklauso nuo GPU negu nuo CPU (nenaudojant programiškai specialiai silpnesniems GPU mažesnio galingumo, našumo), jei renderina iš tikro tik CPU, o GPU tik išveda vaizdą į monitorių?
Galima paaiškinti štai kaip:
CPU su daug core'ių ar 40-400 GHz dažniu (bet be corių), spėja nurenderinti sceną ir po kiekvieno pikselio atrenderinimo perduoda ta pixelio spalvą į GPU VRAM, bet GPU veikiantis mažu dažniu lėčiau išvedinėja pixelius į monitorių ir jam reikia ilgesnio laukimo kol prisijungs prie savo VRAM. Žodžiu, galėtų silpnesniems, lėtesniems GPU jo VRAM veikti irgi žemesniu dažniu ir CPU tada lėčiau deda 2D bitmap'ą į tuos lėtesnius VRAM ir gaunas kad viskas veikia lėčiau su silpensniu GPU (ir su lėtesniais VRAM specialiai nustatytiems tam silpnam GPU).
Bet tada išeitų, kad jeigu sunkus grafiškai žaidimas ir veikia su mažai FPS, kaip 15-25 FPS, tai renderinimo greitis turėtų beveik nepriklausyt ar naudojamas galingas (greitas) GPU ar silpnas (lėtas) GPU. Nes daugiausiai renderinimo laiko butų skirta pačiam renderinimui, o ne 2D paveiksliuko išvedimui į lėtą ar greitą VRAM atmintį.
Tai šita teorija kaip ir atkrenta. Nebent CPU dar naudoja GPU atmintį ne tik 2D suprojektuoto paveiksliuko išvedimui, bet dar naudoja tą informaciją (iš VRAM) visokiems Bloom (šviesių spalvų išliejimas), ar pavyzdžiui, pixelio gylio koordinatės lyginimui su kitų trikampių pikseliais (kai suprojektuotų trikampių x ir y koordinatės ant ekrano tos pačios, bet gylio koordinatė z skiriasi). Išrenkamas pikeselis ant arčiausiai prie kameros esančio trikampio, kai pločio x ir aukščio y koordinatės (ant ekrano) kelių trikampių vienodos.


Kalbant apie šviesos ir elektros greitį į kurį remiasi CPU ir GPU veikimai, tai ten kur mokslininai su elektros prietaisais matuoja šviesos ar elektros greitį, gali būti, kad jie matuoja tiesiog prietaiso regavimo greitį, o tikrasis šviesos ir elektros greitis gali būti didesnis nei 300 tūkstančių km/s.


Papildymas-pataisymas.
AMD Ryzen 9 3900X (12 core, 3.8-4.6 GHz, 2019 metų) procesorius Free Pascal testuose veikia apie 3 kartus (tiksliau 2.8 karto) greičiau nei AMD FX 8350 Eight-Core (4-4.2 GHz, dažniausiai gali veikti tik kaip 4 core'ių procesorius, nes dviems core'iams tenka vienas FPU AMD FX) procesorius arba AMD Athlon 64 X2 5000+ (2.6 GHz, 2 core, 2006 metų) procesorius. AMD FX 8350 ir AMD Athlon 64 X2 5000+ mano Free Pascal testuose veikia apytiksliai tokiu pat greičiu, jei linijiniai padidinti procesoriaus AMD FX 8350 skaičiavimo laiką 4.16(GHz)/2.6(GHz)=1.6 karto (t. y., jeigu padauginti AMD FX 8350 procesoriaus skaičiavimo laiką iš 1.6 ir palyginti su AMD Athlon 64 X2 5000+ procesoriaus skaičiavimo laiku).
Galima spekuliuoti, kad AMD Ryzen procesoriai tiesiog veikia apie 3 kartus didesniu dažniu nei senesni AMD procesoriai. Beje, AMD Ryzen 9 9900X (4.4-5.6 GHz, 12 core, 2024 metų) 3D žaidimuose veikia apie 1.5 karto greičiau su Nvidia GeForce RTX 4090 vaizdo plokšte nei AMD Ryzen 9 3900X (12 core, 3.8-4.6 GHz, 2019 metų) su Nvidia GeForce RTX 4090 vaizdo plokšte.
Tai sprendžiant iš to kokiu greičius procesoriai sudeda skaičius, daugina, dalina ir atlieka kvadratinės šaknies operacijas, galima pasakyti, kad net 2.8 karto pagreitėjusio (ar padidėjusio dažnio) AMD Ryzen 9 3900X neužtenka, kad vien šito procesoriaus vienu core'iumi renderinta tokio sudetingumo 3D scenas žaidimuose realiu laiku. Todėl galima tik spekuliuoti apie grafinių plokščių daug didesnius dažnius nei CPU (jei manyt, kad GPU pats neturi jokių core'ių). Nebent ten kažkaip labai ekonomiškai ir optimizuotai renderina tik vienas CPU core 4K rezoliucijoje be upscaling'o su 60 fps. Ir tai dar jeigu tik su naujausiais procesoriais kaip AMD Ryzen 9 9900X (kurių dažnis gali būti pakeltas dar 50 % nuo AMD Ryzen 9 3900X 'tikrojo' 12 GHz dažnio ir sudaryti 12*1.5=18 GHz dažnį). Bet tai yra beveik be šansų.
Cache'o problema yra ta, kad jis iš principo negali veikti pagal mano samprotavimus. Kad suasocijuoti kiekvieną RAM adresą cache'ui reikia daugiau tranzistorių negu yra RAM čipuose. Realiai procesoriaus greitį galima padidinti tik su daugiau registru (kaip, pavyzdžiui, yra ARM procesoriuose palyginus su intel ir AMD procesoriais). Arba jeigu sukurti mažo dydžio kažkokią atmintį, greitesnę už RAM ir leisti procesoriui kreiptis į ją (vietoj RAM kai kurių adresų) tam tikroms programoms. Bet tik jei tuose adresuose visada yra dažniausiai naudojami kodai. Tokiu budu tik tie kodai (arba data) greičiau butų kraunami iš (į) tos mažesnės-greitesnės atminties, o likę kiti kodai RAM atmintyje veiks tokiu pačiu greičiu kaip su normalia RAM atmintim.


Kaip Bill'o Multitasking'as galėtų veikt

[keisti]
Trumpai tariant multitasking'as galėtų veikti frame'ais. Pavyzdžiui, čia: http://davibu.interfree.it/opencl/smallptgpu/smallptGPU.html
yra kažkokia sudetingo apšvietimo renderinimo programa, kuri veikia su AMD ir NVIDIA vaizdo plokštėm. Ji tipo naudoja GPU, ir galima tipo perjungt tarp GPU ir CPU renderinimo, bet man to nepavyko.
Paleidus video ir paleidus šitą smallptGPU viskas veikė vienu metu ir video grojo kol keičiau žiurėjimo kryptį ir kampą tame apšviestų objektų renderinimo lange.
Tai žodžiu, paleidus vieną programą, pvz, video grojimo programą, CPU ar GPU nurenderiną kiekvieną kadrą ir Windows'ai po tos programos paleidimo palieka adresą, kur po vieno kadro ar po tam tikro laiko praėjimo reikia pereiti prie kitos programos, jei tokia paleista arba toliau apdoroti esamą programą (kodą). Todėl galima manyti, kad po kiekvienos programos paliekamas kodas tos programos pačiame gale ar tam tikroje RAM vietoje tos programos, kuris su naujos programos paleidimu atnaujinamas. Tada po kažkokios porcijos atlikimo pirmos programos, CPU arba GPU pereina prie kitos programos nušokdamas į kitą RAM vietą, kur prasideda kitos programos apdorojimas, kaip šiuo atveju būtų renderinimas su smallptGPU. Po kažkokios dalies renderinimo, paliekamas kodas RAM'uose (kai buvo paleista antra programa), kad reikia peršokti į RAM adresą pirmos programos ir vėl darbuotis prie pirmos programos. Ir taip ratu. Paleidus trečią programą, antros programos peršokimo kodas modifikuojamas į trečią programą, o trečia programa po tam tikro mažo progresą pereiną į kodą, kuris peršoka į pirmą programą. Ir taip ratu.
Sunkiausia paaiškinti šituo principu veikiantį multitaskingą ir dar be visokių naujų procesorių naujų instrukcijų mandrybių, kodėl video neveikia greičiau ar lėčiau, nepriklausomai nuo CPU ar GPU apkrovimo. Vadinasi yra kažkoks laikrodis procesoriuje ir galimas daiktas, kad tam tikroms programoms, kaip video grojimas ar vienodas greitis žaidimuose, pasiekiamas tuom, kad procesorius tokioms programoms tam tikrame kodo gabalėlyje specialiai kreipiasi į laikrodį, kad žinoti ar jau reikia renderinti kitą kadrą video playeryje ar nereikia. O žaidime ar reikia jau pastumti visus objektus ir kokiu atstumu priklausomai nuo to kiek laiko praėjo.
Tai vis vien gaunasi, kad turi buti ir laikrodis, o ne tik CPU ir RAM su HDD ir/ar SDD bei imput/output device'ais.
Kad atsisiusti SmallptGPU reikia siustis arba iš aukščiau duoto adreso arba šia nuoroda: http://davibu.interfree.it/opencl/smallptgpu/smallptgpu-v1.6.tgz
Atsisiuntus reikia išpakuoti, pvz, su 7-zip. Tada paleisti SmallptGPU.exe.

Naudingos nuorodos

[keisti]
Registrai IX ir IY (index registrai) gali realiai neegzistuoti.
Dar gali būti, kad negalima dėti FLAGS registro ant STACK su PUSH ir POP instrukcijom (galima dėti tik Program Counter (PC, dar kitaip vadinamu Instruction Pointer (IP)) ant STACK). Nes tokios funkcijos mažai kur reikia ir tikriausiai galima apseiti be to.
Dar gali būti, kad negalima sudėti DE su HL registru, negalima sudėti (ar atimti) BC su HL registru, BC su DE ir panašiai. Nes tada tai bus 16 bitų sudeties operacijos, o procesorius yra 8 bitų ir tam skirtas akumuliatorius A. Teoriškai tai būtų galima padaryti per kažkokias mikroinstrukcijas, bet abejoju ar kas nors tiek vargintųsi, bei negautų žymaus pagreitėjimo nei nuoseklus kodas.
Dar gali būti, kad negalima krauti iš Stack Pointer nukreipiančio RAM adreso į registrus AF (registrrai A ir F (FLAGS)), DE, BC, HL, nes taip kraunami du baitai iš Stack Pointer nurodyto adreso (pirmas baitas) ir tas adresas +1 (antras baitas). Pagal stack pointer (SP) adresą realiai galima krauti iš atminties RAM tik 2 baitus į program counter (PC) arba iš PC į RAM adresą, kurį nurodo SP.
Parodysiu svarbiausius ir sunkiausiai suprantamus žymėjimus Asamblerio kode.
1 Pavyzdys.
LD B, 7.
Tai yra registro B įkrovimo instrukcija skaičiumi 7. Kai Program Counter vis didindamas RAM atminties adresą prieina prie opcode'o LD (kiekvienas adresas saugo vieną baitą arba 8 bitus ir kiekvienas opcode'as, kuris garantuotai veikia yra vieno baito), tai sekantis 16 bitų adresas (kuris yra Program Counter'yje) saugo 8 bitų skaičių 7 dvejatainėje sistemoje (00000111). Po šitos operacijos registras B turės skaičių 7.
Skaičius sekantis po opkodo arba baitas sekantis po opkodo vadinamas imidiate. Imidiate gali buti ir 2 baitai. Tada pvz. RAM adrese 102 yra opcode'as, RAM adrese 103 yra pirmas baitas, RAM adrese 104 yra antras baitas. Du baitai saugomi adresuose 103 ir 104 vadinami 16 bit imidiate value.
2 Pavyzdys.
LD (BC), A.
Tai yra įkrovimo instrukcija. Registras A įkraunamas į RAM adresą, kurį saugo registru pora (registras B ir registras C). Registras BC nurodo RAM adresą į kurį bus kraunami 8 bitai iš akumuliatoriaus A. Kai nurodomas RAM adresas tada operand rašomas skliausteliuose kaip šiuo atveju yra su registru pora BC. Šios instrukcijos opkodas yra 00000010.
3 Pavyzdys.
LD (nn), A.
Iš registro A, kraunamas 8 bitų skaičius ar tiesiog baitas į RAM adresą, kurį nusako pirmas baitas sekantis po opkodo 00110010 ir antras baitas sekantis po pirmo baito. Todėl iš viso šita instrukcija užima 3 baitus (vienas baitas opkodo ir du baitai nurodantys RAM adresą). Opkodas LD šiai instrukcijai yra 00110010. 16 bitų skaičius nn yra imidiate value. O toks adresavimas vadinamas indirect adressing. O gal antram pavyzdyje indirect adressing, o čia imidiate adressing, tai nėra taip svarbu kaip vadinasi.


Dar gali būti, kad Non maskable interrupt neegzistuoja, nes jei toks interrupt įvyktų vydurį kodo, tai nebaigus esamo kodo ir peršokus į input/output kodą, visi registrai bus užpildyti kitu kodu ir grįžus iš interrupt viskas registruose bus prarasta ir nebus galima nieko testi. Net jei buvo tie registrai įkrauti ant STACK. Nes iš stack galima krauti registrus tik po vieną (bet realiai tokios instrukcijos gali neveikt). O kiekvieną kartą krauti visus registrus ant ir iš Stack būtų neekonomiškai ir tam laikui beveik neįmanoma. Kas turėtų vykt automatiškai, o neautomatiškai to padaryti negalima, nes grįžus į seną kodą, jame nebus tokių instrukcijų, kad gražinti senus baitus į registrus iš RAM adreso nurodomo per STACK.
Be to, atrodo intel 8080 neturėjo non maskable interupt instrukcijos.
Taip pat gali neegzistuoti instrukcijos IM 0 (Set Interrupt mode 0), IM 1 (Set Interrupt mode 1), IM 2 (Set Interrupt mode 2), kurios yra dviejų baitų ir kurių neturėjo intel 8080 CPU.


Interupt veikimo principas.
Čia http://www.bitsavers.org/components/intel/8086/9800722-03_The_8086_Family_Users_Manual_Oct79.pdf aprašyta 45 puslapyje kaip veikia Interrupt su intel 8086 procesorium.
Čia
http://cc.bjtu.edu.cn:81/meol/common/script/preview/download_preview.jsp?fileid=1118293&resid=172498&lid=15600&preview=preview
10 puslapyje sutrumpintai aprašyta kaip veikia interupt su intel 8086 procesorium.
Jei egzistuoja tik maskable interrupt intel 8080, Zilog Z80 ir intel 8086 procesoriuose, tai interrupt procesas vyksta tokiu budu. Kai procesorius baigia kokį nors kodo gabaliuką ar didesnį gabalą, tai po to kodo yra instrukcija įjungti maskable interrupt. Tada visi norintis perduoti signalą interrupt device'ai (kaip pelė arba klaviatura arba Flopy disk) siunčią signalą, kad nori perduoti savo informaciją arba, kad juos aptarnautų pagal tam tikrą interrupt rutiną.
Yra du variantai kaip viskas vyksta toliau.
1 variantas. Visi interrupt device'ai sujungti į herarchinę schemą, kai pirmiausia aptarnaujamas svarbiausias device'as, paskui mažiau svarbus, paskui dar mažiau svarbus ir t. t. Aukščiausiai interrupt herarchijoje esantys prietaisas aktyvuoja pvz. intel 8086 procesoriaus Interrupt pin (kojelę). Kiti žemesnės herarchijos prietaisai paliekami laukimo pozicijoje. Tada aukščiausios herarchijos prietaisas per data bus perduoda vieną baitą į procesorių (galimas daiktas, tas baitas padauginamas procesoriumi automatiškai iš 4). Tas baitas reiškia vieną iš 256 adresų skirtingų prietaisų nuorodų RAM atmintyje. Todėl pirmi 256 ar 1024 (jei padaugintas iš 4) RAM adresai yra užimti ir skirti I/O (input/output) funkcijoms. Realiai tai tiek daug (256) prietaisų ant senų kompiuterių negalėjo būti, todėl tiesiog kiekvienas tas adresas saugo neilgą kodo gabaliuką, kuris arba atlieka paprastą interrupt aptarnavimo rutiną arba nukreipią į kitą RAM adresą, kuriame yra sudetingesnė ir ilgesnė interrupt rutina prietaisui, kuriam to reikia.
2 variantas. Antras variantas veikia taip pat kaip 1 variantas, tik visi interrut prietaisai sujungti ne herarchijos principu, o tiesiog interrupt pirmiausia aptarnaujamas tam prietaisui, kuris pasiuntė signalą pirmas. Bet tada butų sunku paaiškinti, ką daryti paskui, kai yra dar keli interrupt po pirmo interrupt. Reikėtų schemos, kuri prisimintu, kuris interrupt buvo pirmas, kuris antras, kuris trečias ir taip toliau.
3 variantas. Prpcesoriai intel 8080 ir Zilog Z80 turi instrukciją RST (restart ar panašiai). Šita instrukcija padaro peršokimą į vieną iš 8 adresų RAM pradžioje, kuri vadinama Page Zero, bet ji nelabai tinka interrupt funkcionavimui.
Tai tiesiog trečias variantas yra, kad po kiekvieno neilgo kodo (kuris dažniausiai buna loop funkcijos - iteracijos) yra jump instrukciją į kokį nors specialų RAM adresą. Tame adrese surašytos visų input/output prietaisų aptarnavimo rutinos. Procesorius pradeda tikrinti visus I/O portus ar jie turi perduoti informaciją, kad nori komunikuoti (kitaip tariant atlikti interrupt). Pvz, jei iš I/O porto perskaitomas per data bus signalas 00000000, tai tas portas nieko perduoti nenori, o jei perduodamas signalas 11111111, tai tas portas pasiruošęs keistis input ir/ar output informacija. Todėl pirmiausiai kiekvienos rutinos kodas patikrina ar CPU su I/O device'u apskritai bendraus. Jeigu bendraus (gautas baitas 11111111), tai seka tolimesnis baitų imimo ar siuntimo kodas iš/į I/O portą.
Tokių budu surašyta daug I/O device'ų rutinų iš eilės ir po visų šitų rutinų patikrinimo ar aptarnavimo gale yra RET instrukcija (Return from Call) kuri gražiną seną PC (program counter) adresą, kuris seka po peršokimo adreso į tas I/O portų aptarnavimo rutinas. Ir pagrindinio kodo vykdymas vyksta toliau.
Šitas trečias variantas yra lėčiausias ir mažiausiai lankstus.
Non maskable interrupt galėtų veikti kaip kompiuterio restartavimas, nes tada nesvarbu, kad viskas dings iš RAM atminties. Tada per data bus atsiunčiamas 8 bitų adresas į RAM ar ROM ar I/O ir nuo ten Program Counter pradeda vykdyti kodą, nekreipdamas dėmesio, kad viskas iš CPU registrų gali dingti, užpildant juos naujom reikšmėm ir tada RET (return from call) instrukcija tampa beprasmiška.


Spekuliacijos apie 8086.
Registrų BP, SI ir DI gali nebūti. Jie daugiausiai naudojami su 4 segment registrais (ES, CS, SS, DS), kurių taip pat gali nebuti intel 8086 CPU ir visuose velesniuose intel procesoriuose. Nes labai gerai galima apseiti ir be segmento registrų (tam reikalui naudoti registrus CX, BX, DX). Jei jau intel norėjo tokio funkcionavimo (kokį duoda segment registrai), tai tiesiog galėjo sukurti daugiau paprastų registrų kaip CX, BX, DX.
Sement registrai teoriškai duoda 8086 procesoriui 20 bitų RAM adresaciją arba 1 Megabaitą vietoje 16 bitų 65 Kilobaitų.
Intel 286 jau gali adresuoti su 24 bitais RAM, kas duoda 16 Megabaitų. Ir kur žinoma reikia segment registrų, kurie gali būti reklaminis triukas reklamuoti palaikymą daugiau nei 64 KB RAM. Nes 386 gali adresuoti 4 GB RAM be segment registrų (arba 4 milijardus adresų; jei kiekviename adrese visada saugomi 64 bitai, tai tada 386 ir šiuolaikiniai ar 32 bitų procesoriai gali adresuoti 4*64/8=32 GB RAM). Amerikiečiai labai nekantrūs tobulėjime.
Intel 286 procesoriaus naujovė yra 4 protection privilage levels skirti operacinei sistemai ir programoms. Jie taip pat gali neegzistuoti. Tipo galima įjungti, kuri nori privilage level ir busi apsaugotas, bet atjungti iš žemesnio privilage level negalima. Tai procesorius turi saugoti RAM adresų privilage level'us, kas atrodo kaip nesamonė. Todėl greičiausiai Operacinė Sistema ir programos saugomos nuo įsilaužimo programiškai, prie ko dar gali prisidėti [Microsoft ar kitos] programavimo kalbos.