Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Siirrettävä ajastin (portable timer)

vuokkosetae [17.10.2014 01:23:05]

#

Eli tahtoisin tehdä asioita 1 min 2s 345 ms +-2ms kuluttua (seinäkellosta).
Siis millisekunnin tarkkuudella toimivaa ajastinta haetaan.

Mitä ajastinta suosittelisitte joka toimisi myös windowsissa ja OS X:ssä.
Boostia katselin ja totesin, etten haluaisi ihan sen möhköyttä tähän mukaan.

C:n clock() saattaisi olla ajan keräämistä varten hyvä lähtökohta, mutta tuo ajastimien käyttö siirrettävästi on hieman hakusessa nyt.

Windowsille saa pthreadsin, joten sen ajastinta voisi ehkä käyttää.

vesikuusi [17.10.2014 08:44:42]

#

Oletko tutustunut standardikirjaston chrono-työkaluihin?

Metabolix [17.10.2014 16:58:49]

#

C:n clock palauttaa ohjelman kuluttaman prosessoriajan (paitsi Windowsissa, jossa se palauttaa todellisen ajan), joten se ei sovellu todellisen ajan mittaamiseen.

Standardissa ei ennestään ollut sekuntia tarkempia välineitä, mutta C++11:n uusi chrono-kirjasto (aiemmin Boost-kirjastojen osa) parantaa tätä tilannetta. Tästä huolimatta järjestelmän kello ei välttämättä oletusasetuksilla mittaa millisekunteja vaan esimerkiksi sadasosia, ja toisaalta tavallisen käyttäjän ohjelma ei välttämättä saa joka järjestelmässä suoritusaikaa noin tarkasti toivotulla hetkellä.

Voit testata kellon tarkkuutta tällä koodilla, joka yrittää nukkua aina 11 millisekuntia ja laskee lopuksi yrityksistä pari tilastollista lukua.

#include <iostream>
#include <chrono>
#include <thread>
#include <valarray>
template <typename T> double ms(T t) {
	return 1e-6 * std::chrono::duration_cast<std::chrono::nanoseconds>(t).count();
}
int main() {
	const auto target = std::chrono::milliseconds(11);
	std::valarray<double> v(std::chrono::seconds(3) / target);
	for (auto& t: v) {
		auto t0 = std::chrono::high_resolution_clock::now();
		std::this_thread::sleep_for(target);
		auto t1 = std::chrono::high_resolution_clock::now();
		t = ms(t1 - t0);
	}
	double avg = v.sum() / v.size();
	double sd = sqrt(pow(v - avg, 2).sum() / (v.size() - 1));
	std::cout << "target = " << ms(target) << "\n";
	std::cout << "tests  = " << v.size() << "\n";
	std::cout << "min    = " << v.min() << "\n";
	std::cout << "max    = " << v.max() << "\n";
	std::cout << "avg    = " << avg << "\n";
	std::cout << "SD     = " << sd << "\n";
}

Omalla koneellani Linuxissa tulos on yllättävänkin hyvä, poikkeamaa tulee vain millisekunnin murto-osia.

Vastaus

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

Tietoa sivustosta