1) Millä käskyllä saisi NOPEASTI täytettyä pätkän muistia tietyllä arvolla? (eli piirrettyä tietyn mittaisen, yksivärisen vaakasuoran viivan näytölle) Entäpä kopioitua muistia paikasta toiseen?
2) Onko kokonais- ja liukuluvuilla operoimisessa nopeuseroa? Eikös nykyisissä koneissa ole matikkaprosessori sisäänrakennettuna?
3) Onko yhteen-, vähennys-, kerto- ja jakolaskussa nykyään nopeuseroa? Entä laskutoimituksissa Windows- ja Dos-ohjelmissa?
1) no jos on saatavilla BC niin käytä BG kirjastoa vähän hidas, mutta nykyisillä koneilla tuskin haittaa
2) on integroitu m-prosessori ollut jo joistain 386 prosessoreista lähtien jolloin sitä ei erikseen tarvinnut jos halusi nopeuttaa konettaa.
3) nyt en ymmärtänyt? Hankala havaita nopeus erot, mutta eiköhän kertolasku ole hitain noista. ???
lainaus:
3) Onko yhteen-, vähennys-, kerto- ja jakolaskussa nykyään nopeuseroa? Entä laskutoimituksissa Windows- ja Dos-ohjelmissa?
Siis kyllä niissä varmasti eroa on. Mutta en tiedä kuinka paljon.
Nyt ehkä hieman offtopikkia, mutta kysytään kuitenkin: kun prosessorin pitäisi laskea kertolasku, niin miten se sen tekee? Jos meillä on lasku x*y, niin looppaako se vain x kertaa ja joka kerralla tulos = tulos + y? Vai tekeekö se sen jotenkin hienommin?
lainaus:
3) nyt en ymmärtänyt? Hankala havaita nopeus erot, mutta eiköhän kertolasku ole hitain noista. ???
Yleensä kaikissa oppaissa neuvotaan välttämään jakolaskua grafiikan piirrossa sen hitauden takia. Ja onhan << nopeampi kuin kertolasku.
Puhun tässä yleisesti juuri x86-arkkitehtuurista.
1) Kopiointiin voit käyttää C-standardikirjaston memcpy-funktiota. Vaakasuoran viivan piirtoon ei tarvinne muuta kuin simppelin loopin, C++-kääntäjät osanneevat optimisoida sen melko hyvin. Molemmat voisi hoitaa tietty myös inline asmilla (rep movsX, tai simppeli looppi). Kokeile itse :-)
2) On eroa, on sisäänrakennettuna. Jos äärimmäistä nopeutta kaipaat, käytä ihmeessä kokonaislukuja tai vaikkapa fixedpointtia. Mutta koneet nopeutuvat ja... no, en usko että kovinkaan moni C++-kooderi enää fixedpointtia käyttää.
3) Kyllä on, sen sijaan Windows ja DOS-ohjelmien laskutoimituksissa ei ole eroja (tietysti eräitä "eroja" voi havaita real- ja suojatun-tilan eroista mutmut.. :-) Yleisesti ottaen hitain mainitsemistasi on jakolasku, sitten kertolasku. Yhteen ja vähennyslaskut ovat yhtä nopeita (mutu).
lainaus:
kun prosessorin pitäisi laskea kertolasku, niin miten se sen tekee? Jos meillä on lasku x*y, niin looppaako se vain x kertaa ja joka kerralla tulos = tulos + y? Vai tekeekö se sen jotenkin hienommin?
mutu(tm): Ei. Tuo jaetaan pienempiin yksittäisiin shiftauksiin ja sitten lisäillään niitä yhteen. Lue esim: http://www.azillionmonkeys.com/qed/amult.html
lainaus:
Yleensä kaikissa oppaissa neuvotaan välttämään jakolaskua grafiikan piirrossa sen hitauden takia. Ja onhan << nopeampi kuin kertolasku.
Kyllä, ja >> on nopeampi tapa jakaa. Monet kääntäjät osaavat nykyään optata kertomiset mm. LEA-käskyiksi, ja se onkin jo melko nopeaa.
edit: Tässä vielä taimaukset DIV:ille ja MUL:ille (HELPPC):
div:
Clocks Size Operands 808x 286 386 486 Bytes reg8 80-90 14 14 16 2 reg16 144-162 22 22 24 2 reg32 - - 38 40 2 mem8 (86-96)+EA 17 17 16 2-4 mem16 (150-168)+EA 25 25 24 2-4 (W88=158-176+EA) mem32 - - 41 40 2-4
mul:
Clocks Size Operands 808x 286 386 486 Bytes reg8 70-77 13 9-14 13-18 2 reg16 118-113 21 9-22 13-26 2 reg32 - - 9-38 13-42 2-4 mem8 (76-83)+EA 16 12-17 13-18 2-4 mem16 (124-139)+EA 24 12-25 13-26 2-4 mem32 - - 12-21 13-42 2-4
lainaus:
1) Millä käskyllä saisi NOPEASTI täytettyä pätkän muistia tietyllä arvolla? (eli piirrettyä tietyn mittaisen, yksivärisen vaakasuoran viivan näytölle) Entäpä kopioitua muistia paikasta toiseen?
Viivasta on hankala sanoa, koska C++ ei tue mitään piirto-operaatioita. Täytyisi tietää käyttöjärjestelmä ja ehkä jopa näyttötila jota käytät.
DOS:ssa tosiaa riittää kun täytät tietyn alueen muistista jollain nollasta poikkeavalla arvolla. Joissain tiloissa täytyy tosin hieman kikkailla ja täyttää joka 4. muistiosoite, en nyt muista enää tarkkaan...
Kääntäjä on Dev-C++ ja kirjasto on SDL.
lainaus:
1) Kopiointiin voit käyttää C-standardikirjaston memcpy-funktiota. Vaakasuoran viivan piirtoon ei tarvinne muuta kuin simppelin loopin, C++-kääntäjät osanneevat optimisoida sen melko hyvin. Molemmat voisi hoitaa tietty myös inline asmilla (rep movsX, tai simppeli looppi). Kokeile itse :-)
No, onko nopeampaa piirtää viivä memcpy:llä vai silmukalla? Mitenkähän seuraavaa silmukkaa oiken voisi optimoida? Värit ovat 16-bittiset.
vari32=(vari16<<16)+vari16; if (x1<0) x1=0; if (x2>=w) x2=w-1; bufp16 = (Uint16 *)screen->pixels+y*w+x1; bufpMax16 = (Uint16 *)screen->pixels+y*w+x2; bufp32 = (Uint32*)bufp; bufpMax32=(Uint32*)bufpMax; for(; bufp32<bufpMax32; bufp32++) bufp32 = vari32; if (xx1 <= xx2) *bufpMax16 = vari16;
Kyllä olen yrittänyt käyttää inline asmia, mutta joko _asm ei toimi, tai sitten olen yrittänyt käyttää sitä väärin. En nyt muista mitä kääntäjä siitä valittaa.
Niin, ja mitä ne LEA-käskyt ovat ja mitä tuo +EA meinaa tuossa taulukossa?
Tuo for-silmukka ei jostain syystä näy oikein. Sen pitäisi olla:
for(; bufp32 PIENEMPI KUIN bufpMax32; bufp32++)
Nyt for-silmukka näkyy jälleen oikein. Minun mokani.
Silmukassa on se vika, että joudut itse huolehtimaan memory alignmentistä, jos kopioit yli 8 bittiä kerrallaan (ts. > 8 bit ei voi lukea&kirjoittaa ihan mistä kohtaa tahansa muistia). X86 ei tietysti moisesta hätkähdä, mutta muut prosessoriarkkitehtuurit heittävät luultavasti voltin. memcpy toimii mainiosti, joten käytä sitä. Huomioi myös, että 32 bit prossissa 16 bitin kopiointi on hitaampaa kuin 8 tai 32 bit.
for(; bufp32<bufpMax32; bufp32++)
Tuota voi optimoida niin, että sijoittaa ++ ennen bufp:tä, eikä sen jälkeen. Jos kääntäjä on tyhmä, se saattaa suorittaa ylimääräistä muuttujan kopiointia.
Aihe on jo aika vanha, joten et voi enää vastata siihen.