Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Muutama C++ -kysymys

Sivun loppuun

tn [03.06.2003 21:48:15]

#

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?

Olli Vanhoja [03.06.2003 22:12:13]

#

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. ???

arcatan [04.06.2003 09:04:24]

#

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?

tn [04.06.2003 12:21:14]

#

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.

thefox [04.06.2003 15:40:12]

#

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

(http://thefox.cracked.org/helppc/)

weicco [04.06.2003 18:02:26]

#

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...

tn [04.06.2003 21:48:16]

#

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?

tn [04.06.2003 21:53:23]

#

Tuo for-silmukka ei jostain syystä näy oikein. Sen pitäisi olla:

for(; bufp32 PIENEMPI KUIN bufpMax32; bufp32++)

Antti Laaksonen [04.06.2003 22:43:47]

#

Nyt for-silmukka näkyy jälleen oikein. Minun mokani.

weicco [05.06.2003 06:59:00]

#

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.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta