Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Prosessoritehon säästö silmukassa

ottis [19.10.2009 19:30:51]

#

Tervehdys.

Olen tässä alkanut opettelemaan C++ koodausta, aikaisempaa ohjelmointiosaamista on PHP:stä joten aivan hakoteillä tässä ei olla.
Kuitenkin eräs asia mietityttää, kaikissa ohjelmissahan on main-functio jonka sisällä on päättymätön looppi joka päättyy vasta kun käyttäjä sulkee ohjelman.
Osasin tutoriaalien pohjalta tehdä yksinkertaisen SDL-kirjastoa käyttävän ohjelman joka lataa bittikarttakuvan, heittää sen näytölle ja sitten sitä kuvaa voi liikuttaa näytöllä nuolinäppäimillä.
Tämä ohjelma toimii muuten ihan hyvin mutta se syö ihan sikana prossua, kaksiytimisestä prossustani toinen on 100% käytössä tällä ohjelmalla. Tämä ilmeisesti johtuu siitä tietokone käy tuota päättymätöntä silmukkaa läpi niin nopeasti kuin koneen tehot antavat myöten.
Minkälaisia ratkaisuja on käytetty siihen että ohjelma ei söisi kaikkea prosessoritehoa silloin kun siihen ei ole tarvetta?

Teuro [19.10.2009 19:40:54]

#

ottis kirjoitti:

kaikissa ohjelmissahan on main-functio jonka sisällä on päättymätön looppi joka päättyy vasta kun käyttäjä sulkee ohjelman.

Väärin ohjelmassa voi olla vain yksi ainoa koodirivi, jonka jälkeen suoritus loppuu.

ottis kirjoitti:

Tämä ohjelma toimii muuten ihan hyvin mutta se syö ihan sikana prossua, kaksiytimisestä prossustani toinen on 100% käytössä tällä ohjelmalla.

Anna prossun nukkua hetken aikaa silmukan lopussa olikos se SDL_Delay(millisekunnit), jolloin suoritus keskeytyy hetkeksi aikaa ja muutkin prosessit saavat prossuaikaa.

Viisaammat voivat jatkaa tästä.

Markus [19.10.2009 19:43:38]

#

Sinun täytyy laittaa ohjelmasi nukkumaan.

Voit joko
a) Nukkua joka kierroksella jonkin pienen vakio ajan (SDL_Delay)
tai mieluummin
b) Nukkua kunnes jotain tapahtuu (SDL_WaitEvent)

ps.
On tietenkin vielä vaihtoehto
c) Mittaa kuinka kauan silmukan suoritus tällä kierroksella kesti ja nuku jostakin vakioajasta jäljelle jäänyt osa:

while (true) {
alku = SDL_GetTicks();
TeeJotain();
loppu = SDL_GetTicks();
SDL_Delay(vakio - (loppu-alku));
}

Mod. lisäsi kooditagit

Metabolix [19.10.2009 19:46:57]

#

A) Voit lukea viestit SDL_WaitEvent-funktiolla, joka odottaa aina, kunnes viesti tulee.

// Ikuinen silmukka.
// Odotetaan aina viestiä.
while (SDL_WaitEvent(&event)) {
  // Käyttäjä teki juuri jotain (liikutti hiirtä, klikkasi, painoi nappia...)
}

Tätä tapaa kannattaa käyttää, jos ohjelma toimii täysin käyttäjän tahtiin. Useimmat hyötyohjelmat ovat tällaisia: jos käyttäjä ei tee mitään, ohjelmakaan ei tee mitään.

B) Voit lisätä silmukkaan tarkistuksen, että jos silmukkaa kierretään liian nopeasti (esim. yli 100 kertaa sekunnissa), nukutaan silmukan lopussa hieman ylimääräistä.

// Olkoon silmukan yhden kierroksen kesto vähintään 10 millisekuntia.
const Uint32 kierrosaika_vah = 10;
Uint32 t_seuraava = SDL_GetTicks() + kierrosaika_vah;

// Ikuinen silmukka.
while (true) {
  // Viestisilmukka: käsitellään jonossa olevat viestit muttei odoteta uusia.
  while (SDL_PollEvent(&event)) {
    // Käyttäjä on sitten viime näkemän ehtinyt kaikenlaista... :)
  }
  // Tähän ne piirustukset ynnä muut...
  // Jos on kulunut liian vähän aikaa, nukutaan hetki.
  if (SDL_GetTicks() < t_seuraava) {
    SDL_Delay(t_seuraava - SDL_GetTicks());
  }
  t_seuraava = SDL_GetTicks() + kierrosaika_vah;
}

Reaaliaikaisessa pelissä tämä jälkimmäinen tapa toimii järkevästi. Eihän ole mitään järkeä lisätä turhaa nukkumista, jos käyttäjän kone on liian hidas eikä pysy pelin vauhdissa muutenkaan; niinpä nukutaan vain, jos nopeus on jo tarpeeksi suuri. Aina pitää muistaa, että olipa määrätty vakio mitä tahansa, jollakulla voi olla niin hidas kone, että jokainen kierros kestää väistämättä liian kauan. Kierros on siis vähintään määrätyn mittainen, ehkä pitempikin.

ankzilla [21.10.2009 19:46:08]

#

Ite oon käyttäny silmukan lopussa SDL_Delay(10):iä..
Jos tuohon pelkkä suora luku laitettaisiin, niin mikä olisi paras mahdollinen millisekuntimäärä, jota ei kuitenkaan perusohjelmissa huomaisi?

Metabolix [21.10.2009 20:21:29]

#

Minusta ei ole mitään syytä käyttää vakioaikaa, ja ainakaan mitään yleispätevää "parasta mahdollista millisekuntimäärää" ei ole, kun tilanne riippuu aina koneesta. Paras vaihtoehto on juuri rajoittaa nopeutta vain liian nopeilla koneilla.

Vastaus

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

Tietoa sivustosta