Olen pitänyt hiukan ohjelmointi(putka)taukoa ja päätin lopettaa tauon esittämällä tyhmiä kysymyksiä.
Olen lukemassa parin muuttujan arvoa toistuvasti ja haluaisin tehdä sen siksi mahdollisimman nopeasti. Käyttäisin mieluummin structia, vaikken tarvitsekaan sitä rakennetta mihinkään muuhun kuin koodin ulkonäköä boostaamaan.
Onko niiden kutsuminen nopeampaa, jos ne eivät ole structin sisällä...
int a, b; for(;;) { a += 1; b += 1; }
...kuin silloin, jos ne ovat:
struct C { int a; int b; }; struct C c; for(;;) { c.a += 1; c.b += 1; }
Vai tekeekö kääntäjä silmukasta täsmälleen samanlaisen molemmissa tapauksissa, kuten oletan?
___________________
Sitten toinen kysymys, joka kanssa tuli mieleeni. Miten varaan muistiin vaikkapa bittikartan, jonka kokoa en vielä käännösvaiheessa tiedä, varaamatta muistia enempää kuin bittikartta tarvitsee? Eli tarkoitus olisi tunkea muistiin useampi erikokoinen kuva ja sitten taulukko, josta löytyy viittaukset jokaisen kuvan alkuun. Kuvia pitäisi saada niin paljon, että pikseleiden erikseen tallentaminen yhteen char-taulukkoon ei onnistu; kääntäjä ei riittävän suurta taulua anna luoda, ja tässähän tapauksessa osa taulukolle varatuista pikseleistä jäisi todennäköisesti käyttämättä. SDL_Surface on tähän asti pelastanut, mutta tässä se ei kertakaikkiaan toimi.
Puhveli kirjoitti:
Olen lukemassa parin muuttujan arvoa toistuvasti ja haluaisin tehdä sen siksi mahdollisimman nopeasti.
Kuulostaa ennenaikaiselta optimoinnilta, jonka sanotaan olevan pahasta.
Puhveli kirjoitti:
Onko niiden kutsuminen nopeampaa, jos ne eivät ole structin sisällä...
Vai tekeekö kääntäjä silmukasta täsmälleen samanlaisen molemmissa tapauksissa, kuten oletan?
Koska rakenteet ovat erilaisia, mitään takeita nopeuseroista tai samanlaisuudesta ei ole. Kunnolliset optimoivat kääntäjät tekevät näistä käytännössä joko ihan samaa binääriä tai ainakin sellaista, jossa nopeusero on olematon.
Koodi kirjoitetaan ihmisiä varten, joten on tärkeämpää miettiä, mitä kirjoitettu koodi tarkoittaa. Jos koodissa on kaksi erillistä muuttujaa, siinä on sitten kaksi enemmän tai vähemmän itsenäistä ja toisistaan riippumatonta asiaa. Jos muuttujat ovat structin sisällä, niillä yleensä ymmärretään olevan jonkinlainen kytkentä; ne eivät ole niin itsenäisiä, kun ne ovat struct-olion ominaisuuksia.
Puhveli kirjoitti:
Miten varaan muistiin vaikkapa bittikartan, jonka kokoa en vielä käännösvaiheessa tiedä, varaamatta muistia enempää kuin bittikartta tarvitsee?
Tähän käytetään osoittimia ja dynaamista muistinvarausta. C:ssä on funktiot malloc
ja free
. C++:ssa vaihtoehto voisi olla vaikka std::deque
, jossa on std::vector
:eita, ellei sitten välttämättä halua tehdä muistinhallintaa (ja bugeja) kokonaan käsin ja käyttää new
- ja delete
-operaattoreita.
Kiitän. C-"osaamiseni" rajoittuu tosiaan lähinnä putkan neliosaiseen oppimäärään, joissa ei mallocia tai freetä kesytelty, enkä ole niihin viitsinyt perehtyä kun en ole oikein tiennyt mitä ne tekevät. Näillä eväillä osannen jatkaa itse.
Puhveli kirjoitti:
Onko niiden kutsuminen nopeampaa, jos ne eivät ole structin sisällä...
– –
Vai tekeekö kääntäjä silmukasta täsmälleen samanlaisen molemmissa tapauksissa, kuten oletan?
Kääntäjän lopputuotoksia voi ainakin GCC:n eli MinGW:n kanssa ihmetellä lipulla -S
, joka siis tuottaa Assembly-tulosteen. Mitä luultavimmin eroa noilla kahdella ei ole, eihän (x86-)prosessori tunne structeja.
Puhveli kirjoitti:
Sitten toinen kysymys, joka kanssa tuli mieleeni. Miten varaan muistiin vaikkapa bittikartan, jonka kokoa en vielä käännösvaiheessa tiedä, varaamatta muistia enempää kuin bittikartta tarvitsee?
Pieni esimerkki, kun nyt kirjoittamaan rupesin... :P
int *lukuja; // int lukuja[N] int **lukuosoittimia; // int * lukuosoittimia[M] lukuja = malloc(N * sizeof(int)); // Tilaa N luvulle lukuosoittimia = malloc(M * sizeof(int*)); // M osoitinta lukuja[0] = lukuja[N - 1] = 0x1337; lukuosoittimia[0] = &lukuja[N - 1]; free(lukuja); free(lukuosoittimia);
Puhveli, jos voit osoittaa valmiista koodista, että structin kentän valinta hidastaa silmukkaa, voit korjata ongelman sitten. Siirrät vain valinnan ulos silmukasta käyttämällä väliaikaista muuttujaa silmukan ajan. Tee siis asia ensin oikein ja tee optimointi vain, jos todella on tarve.
Veikkaan, että tarvetta muutokseen ei tule. Pointtini on kuitenkin se, että yrität tehdä nyt valintaa, jonka voit tehdä myöhemmin.
Optimointineuvoja kysyessä on muuten ihan OK idea näyttää pari riviä sitä oikeaa koodia. Monesti joku toinen voi keksiä optimoinnin, jolla on paljon enemmän merkitystä kuin näillä matalan tason jutuilla. Ei tarvitse ainakaan kuunnella nillitystä, että tee se ohjelma ensin, optimoi sitten :-)
Aihe on jo aika vanha, joten et voi enää vastata siihen.